Interleaving String -- leetcode
来源:互联网 发布:软件下载系统网站源码 编辑:程序博客网 时间:2024/06/06 16:48
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc"
,
s2 = "dbbca"
,
When s3 = "aadbbcbcac"
, return true.
When s3 = "aadbbbaccc"
, return false.
算法一,递归
假定s1[i]和s2[j]之前的字符,和s3[i+j+1]之前的字符,已经满足interleave条件,则添加新字符是否能组成新的interleave的条件为:
若 s1[i] == s3[i+j+1] 或者 s2[j] == s3[i+j+1]
class Solution {public: bool isInterleave(string s1, string s2, string s3) { return helper(s1.data(), s2.data(), s3.data()); } bool helper(const char *s1, const char *s2, const char *s3) { if (!*s3) return !*s1 && !*s2; return *s1 == *s3 && helper(s1+1, s2, s3+1) || *s2 == *s3 && helper(s1, s2+1, s3+1); }};
但是简单递归,时间是却无法被AC。如下面的这样的case:
s1 = "bbbbbabbbbabaababaaaabbababbaaabbabbaaabaaaaababbbababbbbbabbbbababbabaabababbbaabababababbbaaababaa",
s2 = "babaaaabbababbbabbbbaabaabbaabbbbaabaaabaababaaaabaaabbaaabaaaabaabaabbbbbbbbbbbabaaabbababbabbabaab",
s3 ="babbbabbbaaabbababbbbababaabbabaabaaabbbbabbbaaabbbaaaaabbbbaabbaaabababbaaaaaabababbababaababbababbbababbbbaaaabaabbabbaaaaabbabbaaaabbbaabaaabaababaababbaaabbbbbabbbbaabbabaabbbbabaaabbababbabbabbab"
稍微改进了一下,加入访问标志。这下运行时间也能被AC了。下面代码在leetcode上实际执行时间为5ms。
visited访问标志,表示,该对位置(s1,s2),是否已经被判断过,如果已经判断过。则说明从该位置继续下去没有意义。因为如果行,则早就成功了。注,虽然地址是64bit的,但由于字符串是连续的。所以用低32bit,足已代表该地址。
class Solution {public: bool isInterleave(string s1, string s2, string s3) { unordered_set<uint64_t> visited; return helper(s1.data(), s2.data(), s3.data(), visited); } bool helper(const char *s1, const char *s2, const char *s3, unordered_set<uint64_t> &visited) { if (!*s3) return !*s1 && !*s2; const uint64_t xy = (uint64_t)s1 << 32 | ((uint64_t)s2 & 0xffffffff); if (visited.find(xy) != visited.end()) return false; visited.insert(xy); return *s1 == *s3 && helper(s1+1, s2, s3+1, visited) || *s2 == *s3 && helper(s1, s2+1, s3+1, visited); }};
算法二:
dp[i][j]表示, s1的[0,i]子串,s2的[0,j]的子串,是否能满足s3的[0, i+j+1]子串的interleave关系。
要求出dp[i][j],需要 dp[i-1][j] 和 dp[i][j-1]两个历史信息。
即: dp[i][j] = dp[i-1][j] && s1[i] == s3[i+j+1] || dp[i][j-1] && s2[j] == s3[i+j+1];
需要一个二维的数组做辅助空间。
但是,由于所需的历史信息,其实是当前的列的前一行,以及当前的行的前一列。 即正上和正左。
这样的情况,可以用滚动数组,去代替二维数组。
即,只需要保留上一行的信息,以及前一列的信息。
故只需要一维数组就行了。 为进一步进省内存,可以选择较短字符的长度作为辅助空间。
class Solution {public: bool isInterleave(string s1, string s2, string s3) { if (s1.size() + s2.size() != s3.size()) return false; if (s2.size() > s1.size()) s2.swap(s1); vector<char> dp(s2.size()+1); dp[0] = 1; for (int j=0; j<s2.size(); j++) dp[j+1] = dp[j] && s2[j] == s3[j]; for (int i=0; i<s1.size(); i++) { dp[0] = dp[0] && s1[i] == s3[i]; for (int j=0; j<s2.size(); j++) { dp[j+1] = dp[j] && s2[j] == s3[i+j+1] || dp[j+1] && s1[i] == s3[i+j+1]; } } return dp[s2.size()]; }};
算法三:宽度优先搜索
假如 s1 = "aab" and s2 = "abc". s3 = "aaabcb". s1和s2可以组成一个棋盘,或者晶格。如下:
问题就可以转变成,从左上角,到右下角,寻找一条路径,使得路径所经过的字符为s3。
路径上,每一步,只能向右或者向下。
而广度优先搜索,是非常适合处理该问题的。
o--a--o--b--o--c--o| | | |a a a a| | | |o--a--o--b--o--c--o| | | |a a a a| | | |o--a--o--b--o--c--o| | | |b b b b| | | |o--a--o--b--o--c--o
该代码在leetcode上实际执行时间为5ms。class Solution {public: bool isInterleave(string s1, string s2, string s3) { if (s1.size() + s2.size() != s3.size()) return false; unordered_set<uint64_t> visited; queue<uint64_t> q; q.push(0); q.push(-1); int level = 0; while (!(q.size() == 1 && q.front() == -1)) { const auto xy = q.front(); q.pop(); const uint64_t x = xy & 0xffffffff; const uint64_t y = xy >> 32; if (x == s1.size() && y == s2.size()) return true; else if (xy == -1) { q.push(xy); ++level; continue; } if (visited.find(xy) != visited.end()) continue; visited.insert(xy); if (x < s1.size() && s1[x] == s3[level]) q.push(y << 32 | x+1); if (y < s2.size() && s2[y] == s3[level]) q.push((y+1) << 32 | x); } return false; }};
该算法参考自:
https://leetcode.com/discuss/19973/8ms-c-solution-using-bfs-with-explanation
- LeetCode: Interleaving String
- LeetCode Interleaving String
- LeetCode: Interleaving String
- [Leetcode] Interleaving String
- [LeetCode] Interleaving String
- leetcode 68: Interleaving String
- [Leetcode] Interleaving String
- LeetCode - Interleaving String
- [LeetCode]Interleaving String
- LeetCode: Interleaving String
- Leetcode: Interleaving String
- [Leetcode]Interleaving String
- Leetcode: Interleaving String
- LeetCode:Interleaving String
- LeetCode-Interleaving String
- [leetcode] Interleaving String@DP
- LeetCode:Interleaving String
- LeetCode - Interleaving String
- 左移运算符 注意点
- UVa11181 - Probability|Given(离散条件概率)
- ACM-ICPC Live Archive 6811 - Irrigation Lines
- C语言二分图匹配(3)___Makers of Fine Wands since 382 BC(Hdu 1179)
- javascript学习实录 之八(计算所选商品总价值
- Interleaving String -- leetcode
- matlab注释的方法
- 二叉树的遍历
- javascript学习实录 之六(div开关闭合效果实例)
- 导航栏背景图片
- Spring MVC的自动转换功能 HttpMessageConverter
- POJ 3321 Apple Tree(树状数组)
- javascript学习实录 之四(DOM简介)
- javascript学习实录 之三(对象原型引用prototype