常见字符串算法题

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"。

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

猜你喜欢

转载自www.cnblogs.com/sclczk/p/11101963.html