zoukankan      html  css  js  c++  java
  • 常见字符串算法题

    1. 拓扑结构相同的子树

    对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同,节点取值也要相同。

    给定两棵二叉树的头结点AB,请返回一个bool值,代表A中是否存在一棵同构于B的子树。

    思路1:遍历树A,若遍历到的节点C取值与B的根节点取值一样,则判断以B为根和以C为根的树结构是否相同。时间复杂度:O(N*M)。 N:A的节点数,M:B的节点数。
    思路2:将树A和树B序列化为字符串,然后用KMP算法在字符串A中寻找子串B。时间复杂度:O(N+M)
    知识点:树的遍历;树结构匹配;树的序列化;KMP算法
     1 // 思路1
     2 /*
     3 struct TreeNode {
     4     int val;
     5     struct TreeNode *left;
     6     struct TreeNode *right;
     7     TreeNode(int x) :
     8             val(x), left(NULL), right(NULL) {
     9     }
    10 };*/
    11 
    12 class IdenticalTree {
    13 public:
    14     bool chkIdentical(TreeNode* A, TreeNode* B) {
    15         if (B==NULL) return true;
    16         return pre_order(A, B);
    17     }
    18     bool pre_order(TreeNode* A, TreeNode* B){
    19         if(A==NULL) return false;
    20         bool flag=false;
    21         if(A->val == B->val)
    22             flag = judge(A, B);
    23         if(flag) 
    24             return true;
    25         else
    26             return pre_order(A->left, B) || pre_order(A->right, B);
    27     }
    28     
    29     bool judge(TreeNode* root1, TreeNode* root2){
    30         if(root1 == NULL && root2 == NULL) return true;
    31         if(root1 == NULL && root2 != NULL) return false;
    32         if(root1 != NULL && root2 == NULL) return false;
    33         if(root1->val != root2->val) return false;
    34         return judge(root1->left, root2->left) && judge(root1->right, root2->right);
    35     }
    36 };
    View Code
     1 // 思路2
     2 /*
     3 struct TreeNode {
     4     int val;
     5     struct TreeNode *left;
     6     struct TreeNode *right;
     7     TreeNode(int x) :
     8             val(x), left(NULL), right(NULL) {
     9     }
    10 };*/
    11 
    12 class IdenticalTree {
    13 public:
    14     bool chkIdentical(TreeNode* A, TreeNode* B) {
    15         string strA = pre_serial(A);
    16         string strB = pre_serial(B);
    17         int idx = kmp_search(strA, strB);
    18         return idx != -1;
    19     }
    20     
    21     string pre_serial(TreeNode* root){
    22         if(root==NULL) return "#!";
    23         string res = std::to_string(root->val)+"!";
    24         res += pre_serial(root->left);
    25         res += pre_serial(root->right);
    26         return res;
    27     }
    28     
    29     int kmp_search(string s, string p){
    30         int len_s=s.length(), len_p=p.length();
    31         int* next = getNext(p);
    32         int i=0, j=0;
    33         while(i<len_s && j<len_p){
    34             if(s[i] == p[j] || j==-1){
    35                 ++i;
    36                 ++j;
    37             }else{
    38                 j = next[j];
    39             }
    40         }
    41         return j==len_p ? i-j : -1;
    42     }
    43     
    44     int* getNext(string p){
    45         int len = p.length();
    46         int* next = new int[len];
    47         next[0] = -1;
    48         
    49         int k=-1, j=0;
    50         while(j<len-1){
    51             if(k==-1 || p[j]==p[k]){
    52                 if(p[j+1] == p[k+1])
    53                     next[++j] = next[++k];
    54                 else
    55                     next[++j] = ++k;
    56             }else
    57                 k = next[k];
    58         }
    59         return next;
    60     }
    61 };
    View Code

    2. 词语变形题

    对于两个字符串A和B,如果A和B中出现的字符种类相同且每种字符出现的次数相同,则A和B互为变形词,请设计一个高效算法,检查两给定串是否互为变形词。

    给定两个字符串AB及他们的长度,请返回一个bool值,代表他们是否互为变形词。

    思路:C++字符的取值范围为0-255,Java为0-65535。可以设置一个大小为256的数组,存储A中出现的每个字符的计数。B同理。然后比较两个计数数组是否相等。

    知识点:字符取值范围;给定取值范围时,可用数组模拟哈希表,效率更高。

     1 class Transform {
     2 public:
     3     bool chkTransform(string A, int lena, string B, int lenb) {
     4         int* cntA=new int[256]();
     5         int* cntB=new int[256]();
     6         for(int i=0; i<lena; ++i)
     7             ++cntA[A[i]];
     8         for(int i=0; i<lenb; ++i)
     9             ++cntB[B[i]];
    10         for(int i=0; i<256; ++i)
    11             if(cntA[i] != cntB[i])
    12                 return false;
    13         return true;
    14     }
    15 };
    View Code

    3. 判断串的旋转

    如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。比如A="12345",A的旋转词有"12345","23451","34512","45123"和"51234"。对于两个字符串A和B,请判断A和B是否互为旋转词。

    给定两个字符串AB及他们的长度lenalenb,请返回一个bool值,代表他们是否互为旋转词。

    思路:令C=A+A, 然后在C中用KMP算法查找子串B。

    4. 句子的逆序

    给定一个原字符串A和他的长度,请返回逆序后的字符串。如输入:"dog loves pig",13,返回:"pig loves dog"。

    思路:实现一个逆序函数,然后对整个句子逆序,然后对单词逆序。

     5. 最大回文子串 LeetCode 5

     1 class Solution {
     2 public:
     3     string longestPalindrome(string s) {
     4         int len = 0;
     5         string str;
     6         // 遍历每一个位置,作为中心点
     7         for(int i=0; i<s.size(); ++i)
     8         {
     9             // 查找aba模式回文串
    10             for(int j=0; i-j>=0 && i+j<s.size(); ++j)
    11                 if(s[i-j] == s[i+j])
    12                 {
    13                     if(2*j+1 > len)
    14                     {
    15                         str = s.substr(i-j, 2*j+1);
    16                         len = 2*j+1;
    17                     }
    18                 }
    19                 else break;
    20             // 查找abba模式回文串
    21             for(int l=i,r=i+1; l>=0&&r<s.size(); --l,++r)
    22                 if(s[l] == s[r])
    23                 {
    24                     if(r-l+1 > len)
    25                     {
    26                         str = s.substr(l, r-l+1);
    27                         len = r-l+1;
    28                     }
    29                 }
    30                 else break;
    31         }
    32         return str;
    33     }
    34 };
    View Code
  • 相关阅读:
    此生对我影响最大的三位老师
    介绍自己
    介绍自己
    第三周作业
    第二周作业
    PTA编程总结3
    PTA编程总结2
    PTA编程总结1
    2019年春季学期第七周作业.
    2019年春季学期第六周作业.
  • 原文地址:https://www.cnblogs.com/sclczk/p/11101963.html
Copyright © 2011-2022 走看看