LeetCode 392.判断子序列(动态规划、双指针)

题目描述:

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

简单来说,t字符串包含s字符串中的所有字符,且顺序相同。

1.双指针法:

思路:定义两个变量指针,lens、lent,分别从s、t的开头一直往后遍历

第一种情况:如果s[lens]==t[lent],表示s[lens]之前的字符都可以在t字符串中顺序出现,接着lens++,lent++,继续判断s中下一个字符是否可以在t中顺序出现。

第二种情况:s[lens]!=t[lent],表示s[lens]暂时还没有在t中顺序出现,所以lent++,继续判断t中下一个字符是否可以让s[lens]在t中顺序出现。

代码:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int lens=0,lent=0; //定义指针
        while(lens

注意:循环结束后,如果lens!=s.size(),说明s中还有后面的一些字符不能够在t中顺序出现,即s不为t的子序列。

2.动态规划实现:

思路:

状态:定义dp[i][j]表示s中从开头到第i个的子字符串是否为t中从开头到第j个子字符串的子序列。

状态转移方程:

当s[i]==t[j]时,则字符s[i]一定是字符t[j]的子序列,如果s中0~i-1的子字符串是t中0~j-1子字符串的子序列,则dp[i][j]=true,有dp[i][j]=dp[i-1][j-1],比如:字符串A:"abc"是字符串B:"eabcg"的子序列,如果两个字符串同时添加一个相同的字符,那么字符串A还是字符串B的子序列。同理,字符串A不是字符串B的子序列,再添加一个相同的字符,A也不是B的子序列。

当s[i]!=t[j]时,状态:s中前i个子字符串是否为t中前j个子字符串的子序列,与状态:s中前i个子字符串是否为t中前j-1个子字符串的子序列相同,所以有:dp[i][j]=dp[i][j-1]

初始化:空字符串一定是另一个字符串的子序列,所以dp[0][j]=true;任意非空字符串都不是空字符串的子序列,dp[i>0][0]=false。

结果:dp[lens][lent],s中前lens个子字符串是否为t中前lent个子字符串的子序列。

代码:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int lens=s.size(),lent=t.size(); //长度
        //初始化
        if(lens==0){
            return true;
        }
        if(lens>lent){
            return false;
        }
        bool dp[lens+1][lent+1];
        for(int i=0;i<=lent;i++){
            dp[0][i]=true;
        }
        for(int i=1;i<=lens;i++){
            dp[i][0]=false;
        }
        for(int i=1;i<=lens;i++){ //循环遍历
            for(int j=1;j<=lent;j++){
                if(s[i-1]==t[j-1]){
                    dp[i][j]=dp[i-1][j-1];
                }else{
                    dp[i][j]=dp[i][j-1];
                }
            }
        }
        return dp[lens][lent];
    }
};

你可能感兴趣的:(动态规划,贪心,贪心算法,动态规划,leetcode)