LeetCode題解:Interleaving String的幾種思路
阿新 • • 發佈:2018-12-05
題目要求
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
Example 1:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true
Example 2:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false
注意到interleaving的含義是交錯,也就是說s1、s2在相互交錯以連線為s3時,必須要保證其內部的字元是有序且不可跳過的。
極其簡單的遞迴法
class Solution {
public:
bool find(string s1, string s2, string s3) {
if (s1+s2 == s3) {
return true;
}
if (s1[0] == s3[0] && find(s1.substr(1), s2, s3.substr(1))) {
return true;
}
if (s2[0] == s3[0] && find(s1, s2.substr(1), s3.substr(1))) {
return true;
}
return false;
}
bool isInterleave(string s1, string s2, string s3) {
if (s1.size() + s2.size() != s3.size()) {
return false;
}
return find(s1, s2, s3);
}
};
雖然演算法很優美,但奈何還是倒在了timelimit這一關。
改進了一丟丟的深搜法
所以我們要想一下,為什麼一開始的深搜會跑得那麼慢,時間都消耗在哪一步了呢?遞迴最大的弊端在於重複計算,考慮這樣一種情況:某時刻s1和s2的前5和前4個字串構成了s3的前九個,記為(5,4)。接下來,是(6,4),(6,5)…但最終無法完成匹配。於是程式重新回到了(5,4),接下來是(5,5),(6,5),在上述那種演算法下,就會重複計算(6,5)之後註定會錯誤的解。
改進思路:
- 記錄所走過的路徑。
- 考慮當s1已經全部加入s3時,只需比較s2和s3剩餘的部分是否一致。
class Solution {
int m[200][200];
public:
bool dfs(string s1, string s2, string s3, int i1, int i2, int i3) {
if (m[i1][i2]) {
return false;
}
if (i2 == s2.size()) {
return (s1.substr(i1)==s3.substr(i3));
}
if (i1 == s1.size()) {
return (s2.substr(i2)==s3.substr(i3));
}
if (s1[i1] == s3[i3] && dfs(s1, s2, s3, i1+1, i2, i3+1)) {
return true;
}
if (s2[i2] == s3[i3] && dfs(s1, s2, s3, i1, i2+1, i3+1)) {
return true;
}
m[i1][i2] = 1;
return false;
}
bool isInterleave(string s1, string s2, string s3) {
if (s1.size() + s2.size() != s3.size()) {
return false;
}
return dfs(s1, s2, s3, 0, 0, 0);
}
};
嘻嘻嘻,撒花兒~