其他分享
首页 > 其他分享> > 力扣 题目97- 交错字符串

力扣 题目97- 交错字符串

作者:互联网

题目

题解

首先就想的是动态规划法 用dp[i][j] ->即当s1取长度i s2取长度j时是否满足 需要注意的是当其中一个字符串为0 则另一个字符串必须全部与s3匹配才为1

int n1 = s1.size(), n2 = s2.size();
        vector<vector<bool>> dp(n1+1,vector<bool>(n2+1));
        dp[0][0] = true;
        for(int i=1;i<=n1;++i)
        {
            dp[i][0] = dp[i-1][0]&&(s1[i-1]==s3[i-1]);
        }
        for(int i=1;i<=n2;++i)
        {
            dp[0][i] = dp[0][i-1]&&(s2[i-1]==s3[i-1]);
        }
        for(int i=1;i<=n1;i++)
        {
            for(int j=1;j<=n2;j++)
            {
                dp[i][j] = dp[i-1][j]&&s1[i-1]==s3[i-1+j]||dp[i][j-1]&&s2[j-1]==s3[i-1+j];
            }
        }

 当然这是很容易想到的 动态规划 但是

进阶:您能否仅使用 O(s2.length) 额外的内存空间来解决它?

我们针对中心循环进行分析

 for(int i=1;i<=n1;i++)
        {
            for(int j=1;j<=n2;j++)
            {
                dp[i][j] = dp[i-1][j]&&s1[i-1]==s3[i-1+j]||dp[i][j-1]&&s2[j-1]==s3[i-1+j];
            }
        }

dp[i-1][j]意味着如果使用s1字符 那么之前的s1字符必须可行 同理dp[i][j-1]意味着如果这里使用s2字符 那么之前的s2字符必须可行

那么两个值是怎么来的呢 

dp[i-1][j]是来自当i=i-1时循环出来的 也就是上一层的循环

而dp[i][j-1]则是上一次循环得到的

我们发现 每一轮 层数最多只用到了他的上一层循环的值 而上两层之类的根本没用到!! 那么我们可以进行覆盖操作 只用一行容器 将新一轮的数据覆盖掉旧的数据 

然后 我们就使用dp[j] 去代表s2 就可以了 然后每一轮都覆盖一遍 dp[i-1][j]->dp[j] dp[i][j-1]->dp[j-1]

 for (int i = 1; i <= n1; i++) {
            for (int j = 0; j <= n2; j++) {
                //j=0时 意味着s2不取 只看s1是否和s3匹配
                //j!=0时 dp[j - 1] && s2[j - 1] == s3[i + j - 1]-> dp[j - 1]是上一次循环的结果即s2少一个字符 这里是否取s2的字符
                //dp[j] && s1[i - 1] == s3[i + j - 1] dp[j]是上一轮循环的结果即s1少一个字符 意思是这里是否取s1的字符
                dp[j] = j==0?  (dp[0] && s1[i - 1] == s3[i - 1]):
                      (dp[j - 1] && s2[j - 1] == s3[i + j - 1]) || (dp[j] && s1[i - 1] == s3[i + j - 1]);
            }
        }

代码

 1 #include<iostream>
 2 #include<string>
 3 #include<vector>
 4 using namespace std;
 5 class Solution {
 6 public:
 7     bool isInterleave(string s1, string s2, string s3) {
 8         if (s1.size() + s2.size() != s3.size()) {
 9             return false;
10         } 
11         int n1 = s1.size(), n2 = s2.size();
12         vector<bool> dp(vector<bool>(n2 + 1, false));
13         //s2为0时的情况
14         dp[0] = true;
15         //s1为0的情况 只看s2是否和s3匹配
16         for (int j = 1; j <= n2&& s2[j - 1] == s3[j - 1]; j++) {
17             dp[j] = true;
18         }
19         for (int i = 1; i <= n1; i++) {
20             for (int j = 0; j <= n2; j++) {
21                 //j=0时 意味着s2不取 只看s1是否和s3匹配
22                 //j!=0时 dp[j - 1] && s2[j - 1] == s3[i + j - 1]-> dp[j - 1]是上一次循环的结果即s2少一个字符 这里是否取s2的字符
23                 //dp[j] && s1[i - 1] == s3[i + j - 1] dp[j]是上一轮循环的结果即s1少一个字符 意思是这里是否取s1的字符
24                 dp[j] = j==0?  (dp[0] && s1[i - 1] == s3[i - 1]):
25                       (dp[j - 1] && s2[j - 1] == s3[i + j - 1]) || (dp[j] && s1[i - 1] == s3[i + j - 1]);
26             }
27         }
28         return dp[n2];
29     }
30 };
31 
32 int main() {
33     Solution sol;
34     string s1 = "aabcc"; 
35     string s2 = "dbbca";
36     string s3 = "aadbbcbcac";
37     bool result=sol.isInterleave(s1,s2,s3);
38     cout << result << endl;
39 
40 }
View Code

 

标签:字符,s3,s2,s1,力扣,97,&&,字符串,dp
来源: https://www.cnblogs.com/zx469321142/p/16512532.html