【Interleaving String】cpp

题目:

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.

代码:

“merge sort + stack”

        struct LastMatch{
            int i1;
            int i2;
            int i3;
            LastMatch(int i1, int i2, int i3): i1(i1), i2(i2), i3(i3){}
        };
        static bool isInterleave(string s1, string s2, string s3)
        {
            const int n1 = s1.size();
            const int n2 = s2.size();
            const int n3 = s3.size();
            if ( n1+n2 != n3 ) return false;
            stack<LastMatch> sta;
            int i1=0,i2=0,i3=0;
            while ( i1<n1 || i2<n2 || i3<n3 )
            {
                if ( s1[i1]==s2[i2] && s2[i2]==s3[i3] ){
                    sta.push(LastMatch(i1,i2,i3));
                    i1++; i3++;
                }
                else if ( s1[i1]==s3[i3] ){
                    i1++; i3++;
                }
                else if ( s2[i2]==s3[i3] ){
                    i2++; i3++;
                }
                else if ( !sta.empty() ){
                    LastMatch lm = sta.top(); sta.pop();
                    i1 = lm.i1; i2 = lm.i2; i3 = lm.i3;
                    i2++; i3++;
                }
                else{
                    return false;
                }
            }
            return i1==n1 && i2==n2 && i3==n3;
        }

"dp"

class Solution {
public:
        bool isInterleave(string s1, string s2, string s3)
        {
            const int n1 = s1.size();
            const int n2 = s2.size();
            const int n3 = s3.size();
            if ( n1+n2 != n3 ) return false;
            vector<vector<bool> > dp(n1+1, vector<bool>(n2+1, false));
            dp[0][0] = true;
            // check s1 boundary
            for ( int i = 1; i <= n1; ++i ){
                dp[i][0] = s1[i-1]==s3[i-1] && dp[i-1][0];
            }
            // check s2 boundary
            for ( int i = 1; i <= n2; ++i ){
                dp[0][i] = s2[i-1]==s3[i-1] && dp[0][i-1];
            }
            // dp process
            for ( int i = 1; i<=n1; ++i )
            {
                for ( int j = 1; j<=n2; ++j )
                {
                    dp[i][j] = ( s1[i-1]==s3[i+j-1] && dp[i-1][j] )
                    || ( s2[j-1]==s3[i+j-1] && dp[i][j-1] );
                }
            }
            return dp[n1][n2];
        }
};

tips:

这道题第一版采用“merge sort + stack”,有一个大集合过不去,报超时(但即使跟可以AC的dp方法对比,“merge sort+stack”过这个大集合也仅仅慢了不到10%,在数量级上应该没有差别,时间复杂度都是O(n²))

dp的解法是学习网上的解法,理解如下:

dp[i][j]表示s1[0~i-1]与s2[0~j-1]是否匹配s3[0~i+j-1]

因此为了方便,定义dp[n+1][m+1],多一个维度,目的是保证从s1中取的个数从0到n都可以表示(s2同理)。

可以写出来dp的通项公式:

dp[i][j] = ( s1[i-1]==s3[i+j-1] && dp[i-1][j] ) || ( s2[j-1]==s3[i+j-1] && dp[i][j-1] )

表示s3第i+j个元素要么由s1匹配上,要么由s2匹配上。

最后返回dp[n1][n2]就是所需的结果。

整个dp的过程并不复杂,思考下如何得来的:

1. dp取两个维度是因为s1和s2两个变量

2. 之前自己思考dp的时候,考虑的是每个位置可以由s1或者s2其中的元素表示,但是这样考虑起来就太复杂了;网上的思路并么有考虑到这么复杂,而是仅仅考虑s3中总共就这么长字符串,某个长度的字符串可以从s1和s2各取几个。

============================================

上述的dp过程的空间复杂度是O(n²)的,再采用滚动数组方式,把空间复杂度降低到O(n),代码如下:

class Solution {
public:
        bool isInterleave(string s1, string s2, string s3)
        {
            const int n1 = s1.size();
            const int n2 = s2.size();
            const int n3 = s3.size();
            if ( n1+n2 != n3 ) return false;
            vector<bool> dp(n2+1, false);
            // check s2 boundary
            dp[0] = true;
            for ( int i = 1; i<=n2; ++i )
            {
                dp[i] = s2[i-1]==s3[i-1] && dp[i-1];
            }
            // dp process
            for ( int i = 1; i<=n1; ++i )
            {
                dp[0] = s1[i-1]==s3[i-1] && dp[0];
                for ( int j = 1; j<=n2; ++j )
                {
                    dp[j] = ( s1[i-1]==s3[i+j-1] && dp[j] ) || ( s2[j-1]==s3[i+j-1] && dp[j-1] );
                }
            }
            return dp[n2];
        }
};

tips:如果二维的dp过程只跟紧上一次的dp过程有关,就可以退化为滚动数组形式的一维dp过程。

时间: 2024-10-29 05:02:04

【Interleaving String】cpp的相关文章

【Scramble String】cpp

题目: Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively. Below is one possible representation of s1 = "great": great / gr eat / \ / g r e at / a t To scramble the string, we may choo

【Word Break】cpp

题目: Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words. For example, givens = "leetcode",dict = ["leet", "code"]. Return true becau

【Text Justification】cpp

题目: Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified. You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pa

【Simplify Path】cpp

题目: Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", => "/home"path = "/a/./b/../../c/", => "/c" click to show corner cases. Corner Cases: Did you consider the case whe

【Implement strStr() 】cpp

题目: Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Update (2014-11-02):The signature of the function had been updated to return the index instead of the pointer. If you st

【Valid Palindrome】cpp

题目: Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. For example,"A man, a plan, a canal: Panama" is a palindrome."race a car" is not a palindrome. Note:Have you consider tha

【Distinct Subsequences】cpp

题目: Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relat

【实用类String】String类方法的应用案例:查找判断指定字符出现的次数和位置

一.应用要求 输入一个字符串,再输入要查找的字符,判断该字符在该字符串中出现的次数. 二.实现思路 1.使用substring()方法将字符串的每个字符存入数组 2.比较数组每个字符是否与指定的字符相等,并计数 三.编写代码 错误案例: 1 import java.util.Scanner; 2 3 public class StringDemo { 4 5 public static void main(String[] args) { 6 Scanner input = new Scanne

【Palindrome Number】cpp

题目: Determine whether an integer is a palindrome. Do this without extra space. click to show spoilers. Some hints: Could negative integers be palindromes? (ie, -1) If you are thinking of converting the integer to string, note the restriction of using