97. Interleaving String

来源:互联网 发布:java可视化图形界面 编辑:程序博客网 时间:2024/06/10 01:13

Given s1s2s3, 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.

开始理解错了题意,以为s3可以包含多个s1或者s2。如果匹配的话,s3只包含一个s1和s2

递归解法:每次比较s1和s3的最后一个字符或者s2和s3的最后一个字符,如果相等去掉两者的最后一个字符进入子问题,只要一个子问题返回true,父问题就返回true

 isInterleave(s1[0...n1], s2[0...n2], s3[0...n3]) = (s1[n1] == s3[n3] && isInterleave(s1[0...n1-1], s2[0...n2], s3[0...n3-1])) || (s2[n2] == s3[n3] && isInterleave(s1[0...n1], s2[0...n2-1], s3[0...n3-1]))

class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        // IMPORTANT: Please reset any member data you declared, as        // the same Solution instance will be reused for each test case.            return isInterleaveRecur(s1, s1.length()-1, s2, s2.length()-1, s3, s3.length()-1);    }    bool isInterleaveRecur(string &s1, int end1, string &s2, int end2, string &s3, int end3)    {        if(end1 == -1 && end2 == -1 )        {            if(end3 == -1)                return true;            else return false;        }        if(end1 >=0 && s1[end1] == s3[end3] && isInterleaveRecur(s1, end1-1, s2, end2, s3, end3-1))            return true;        if(end2 >=0 && s2[end2] == s3[end3] && isInterleaveRecur(s1, end1, s2, end2-1, s3, end3-1))            return true;        return false;    }};

动态规划解法:根据递归的思想,我们一刻如下使用动态规划解此题。设dp[i][j]表示s1[0...i-1]和s2[0...j-1]能否组合成s3[0....i+j-1],动态规划方程如下                                                                               本文地址

  • dp[i][j] = (dp[i][j-1] ==true && s3[i+j-1] == s2[j-1]) || (dp[i-1][j] == true && s3[i-1+j] == s1[i-1])
  • 初始条件:if(s1[0] == s3[0])dp[1][0] = true  ,  if(s2[0] == s3[0])dp[0][1] = true; 其他值均为false
class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        // IMPORTANT: Please reset any member data you declared, as        // the same Solution instance will be reused for each test case.            const int len1 = s1.length(), len2 = s2.length(), len3 = s3.length();        if(len1 == 0)return s2 == s3;        else if(len2 == 0)return s1 == s3;        // dp[i][j]表示s1[0...i-1]和s2[0...j-1]能否组合成s3[0....i+j-1]        bool dp[len1+1][len2+1];        memset(dp, 0, sizeof(dp));        if(len3 != 0)        {            if(s1[0] == s3[0])dp[1][0] = true;            if(s2[0] == s3[0])dp[0][1] = true;        }        else return false;// len3 = 0,但是len1和len2不等于0        if(len1 + len2 != len3)return false;//长度关系不满足        for(int i = 0; i <= len1; i++)            for(int j = 0; j <= len2; j++)            {                int tmp = i+j-1;                if(j > 0)                {                    if(dp[i][j-1] && s3[tmp] == s2[j-1])                        {dp[i][j] = true; continue;}                }                if(i > 0)                {                    if(dp[i-1][j] && s3[tmp] == s1[i-1])                         dp[i][j] = true;                }            }        if(dp[len1][len2])return true;        else return false;    }};
Lexi的做法为:

卧槽这道还真自己做出来了。感觉是二维DP,尽管没让求什么最大最小个数之类的,只是boolean,但是递推关系还是有的。其实只要把状态敢于定义出来(旁边标注物理意义),状态转移方程就能写出来了。然后就是处理最开始。思路:

  1. 一开始是这么定义的:d[i][j]: whether s1[0, i]的substring和s2[0, j]的substring能够cross match s3[0, i + j + 1]这个substring。比如ab和c,即(0, 1), (0, 0),能否合起来是acb(0, 2)。要点是s3的index要+1,这个一开始就想错了直接i + j的。
  2. d[i][j] = s3[i + j + 1] == s2[j] && d[i][j – 1] == true (用第s2的j个来填s3的i + j + 1个能成功), OR s3[i + j + 1] == s1[i] && d[i – 1][j] == true (用第s1的i个来填s3的i + j + 1个能成功)
  3. d[i][j]物理意义一定要搞清楚,因为d[0][0]说明拿了两个元素,那么它对应的是长度为2的s3,这index干脆就乱套了。这个时候,换一种方式定义:d[0][0]表示从s1中拿0个,s2中拿0个,然后组成s3(长度为0 + 0)能不能成。这个肯定是true。d[1][0]就能表达只从s1中拿一个,s2中不拿,然后组成长度为1的s3这种make sense的意义了。这样i, j就要一直到=size这么大。所以之前的i + j + 1改成i + j – 1,才能真的往string里charAt。
public boolean isInterleave(String s1, String s2, String s3) {  if (s3.length() != s1.length() + s2.length())    return false;  boolean[][] d = new boolean[s1.length() + 1][s2.length() + 1];  d[0][0] = true;  for (int i = 0; i <= s1.length(); i++) {    for (int j = 0; j <= s2.length(); j++) {     if (j > 0 && s3.charAt(i + j - 1) == s2.charAt(j - 1) && d[i][j - 1])       d[i][j] = true;     else if (i > 0 && s3.charAt(i + j - 1) == s1.charAt(i - 1) && d[i - 1][j])       d[i][j] = true;     }  }  return d[s1.length()][s2.length()];}


0 0
原创粉丝点击