97. 交錯字串-7月18日
阿新 • • 發佈:2020-07-18
題目
97. 交錯字串
我的思路和實現
我的思路是給s1,s2和s3各設定一個指標,用來指示當前待匹配的字元 遞迴思路解決: 演算法應該沒有邏輯問題,可是會遞迴+回溯時間複雜度較大,達到了2^n級別class Solution { public: bool result; void recursion(string& s1,int i1,string& s2,int i2,string& s3,int i3){ //printf("s1:%d %c\n",i1,s1[i1]); //遞迴終結條件 if本題官方題解的思路是動態規劃: s1的前i個字元和s2的前j個字元是否能匹配s3的前i+j個字元的條件是:(i3==s3.size()&&i1==s1.size()&&i2==s2.size()){ result=true;return;} //當前層處理邏輯 if(i1<s1.size()) if(s1[i1]==s3[i3]) recursion(s1,i1+1,s2,i2,s3,i3+1); //遞迴到下一層 if(i2<s2.size()) if(s2[i2]==s3[i3]) recursion(s1,i1,s2,i2+1,s3,i3+1);//清除當前層 return; } bool isInterleave(string s1, string s2, string s3) { result = false; recursion(s1,0,s2,0,s3,0); return result; } };
- s1的前i-1個字元和s2的前j個字元與s3的前i+j-1個字元匹配&&s1的第i個字元與s3的第i+j個字元匹配或者
- s1的前i個字元和s2的前j-1個字元與s3的前i+j-1個字元匹配&&s2的第j個字元與s3的第i+j個字元匹配
遞推到最後的結果得到s3得起整個字串能否被s1和s2的兩個字串交叉匹配
有點類似與遍歷一個m*n的二維陣列,每個元素的值取決於其左邊和上面相鄰的元素的值,時間複雜度為m*nclass Solution { public: bool isInterleave(string s1, string s2, string s3) { auto f = vector <int> (s2.size() + 1, false); int n = s1.size(), m = s2.size(), t = s3.size(); if (n + m != t) { return false; } f[0] = true; for (int i = 0; i <= n; ++i) { for (int j = 0; j <= m; ++j) { int p = i + j - 1; if (i > 0) { f[j] &= (s1[i - 1] == s3[p]); } if (j > 0) { f[j] |= (f[j - 1] && s2[j - 1] == s3[p]); } } } return f[m]; } };對比我的沒有記憶化的遞迴方法:
- 為什麼時間複雜度一個是m*n,一個是2^n?
-
- 個人理解是在我的解決方案中,匹配到s1的第i個字元s2的第j字元時,此時程式中是隱式地記錄了具體i+j個字元是怎麼交叉排序的(遞迴函式的呼叫棧);而動態規劃的解決方案中沒有記錄前i+j個字元具體是如何交叉排序的,只記錄了是否前i+j個字元可以匹配!
public: bool result; bool** memo; void recursion(string& s1,int i1,string& s2,int i2,string& s3,int i3){ //printf("s1:%d %c\n",i1,s1[i1]); //遞迴終結條件 if(memo[i1][i2]==false)return; if(i3==s3.size()&&i1==s1.size()&&i2==s2.size()){ result=true;return;} //當前層處理邏輯 if(i1<s1.size()) if(s1[i1]==s3[i3]) recursion(s1,i1+1,s2,i2,s3,i3+1); //遞迴到下一層 if(i2<s2.size()) if(s2[i2]==s3[i3]) recursion(s1,i1,s2,i2+1,s3,i3+1); //清除當前層 memo[i1][i2]=false; return; } bool isInterleave(string s1, string s2, string s3) { result = false; memo = new bool*[s1.size()+1]; for(int i=0;i<s1.size()+1;i++){ memo[i] = new bool[s2.size()+1]; for(int j=0;j<s2.size()+1;j++){ memo[i][j]=true; }} recursion(s1,0,s2,0,s3,0); return result; } };
拓展學習
C++宣告二維陣列
轉自:C++宣告二維陣列
#include <iostream> #include <vector> using namespace std; int rows=2,columns=3;
使用一維陣列模型二維陣列
int a0[] = {1,2,3,4,5,6}; for(int i=0;i<rows;i++){ for(int j=0;j<columns;j++){ cout<<a0[i*columns+j]<<" ";//a0[i*columns+j]等價於a0[i][j] } cout<<endl; }
靜態二維陣列
int a1[2][3] = {1,2,3,4,5,6};
動態二維陣列!要熟練
//申請空間 int** a2 = new int*[rows]; for(int i=0;i<rows;i++) a2[i] = new int[columns]; //釋放空間 for(int i=0;i<rows;i++) delete []a2[i]; delete []a2;
利用vector建立二維陣列
vector<vector<int> > a3(rows,vector<int>(columns)); for(int i=0;i<rows;i++){//初始化 for(int j=0;j<columns;j++){ a3[i][j] = a1[i][j]; } }