LeetCode 115. Distinct Subsequences 递归法(回溯法)/动态规划 int-unsigned int

题目

Given a string S and a string T, count the number of distinct subsequences of S which equals T.

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 relative positions of the remaining characters. (ie, “ACE” is a subsequence of “ABCDE” while “AEC” is not).

Example 1:

Input: S = "rabbbit", T = "rabbit"
Output: 3
Explanation:

As shown below, there are 3 ways you can generate “rabbit” from S.
(The caret symbol ^ means the chosen letters)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
Example 2:

Input: S = "babgbag", T = "bag"
Output: 5
Explanation:

As shown below, there are 5 ways you can generate “bag” from S.
(The caret symbol ^ means the chosen letters)

babgbag
^^ ^
babgbag
^^    ^
babgbag
^    ^^
babgbag
  ^  ^^
babgbag
    ^^^

思路

回溯法

我的第一想法是回溯法,当前能匹配字符匹配或者不匹配,子集树类型

class Solution {
public:
    int numDistinct(string s, string t) {
        int res = 0;
        if(t.length() == 0)return 0;
        backtrack(res,s,t,0,0);
        return res;
    }
    void backtrack(int &res, string s, string t, int s_index, int t_index){
        //满足某个条件,回溯结束
        if(t_index >= t.length()){
            res ++;
            return;
        }
        //不满足继续回溯
        while(t_index < t.length() && s_index < s.length() && s[s_index] != t[t_index])s_index ++;
        if(s_index < s.length()&& s[s_index] == t[t_index] && s.length() - s_index >= t.length() - t.length()){
            backtrack(res,s,t,s_index + 1,t_index + 1);
            //恢复现场,这里是不匹配当前字符
            backtrack(res,s,t,s_index + 1, t_index);
        }
        return;
    }
};

显示为Memory Limit Exceeded,当数据规模较大时问题不能解决
在中间进行剪枝处理后没有解决这个问题

动态规划

这时就考虑到了动态规划,状态res[i][j]表示 S前i + 1位的不同子序列中有几个和T的前j + 1位相同
更新公式

res[i][j] += res[i - 1]res[j]
if(s[i]正好匹配t[j])那么res[i][j] += res[i - 1][j - 1]

具体代码如下:

class Solution {
public:
    int numDistinct(string s, string t) {
        int sn = s.length();
        int tn = t.length();
        if(tn == 0)return 1;
        if(sn == 0)return 0;
        vector<vector<int>>res(sn,vector<int>(tn,0));
        if(s[0] == t[0])res[0][0] = 1;
       // res[0][0] = s[0] == tn[0] ? 1 : 0;
        for(int i = 1; i < sn; i ++){
            res[i][0]+=res[i - 1][0];
            if(s[i] == t[0])res[i][0] ++;
        }
        for(int j = 1; j < tn; j ++){
            for(int i = j; i < sn; i ++){
                res[i][j] += res[i - 1][j];
                if(s[i] == t[j])res[i][j] =res[i - 1][j - 1] + res[i][j]; 
            }
        }       
        return res[sn - 1][tn - 1];
    }

};

测试没有问题,但是提交又有问题了
在这里插入图片描述
这里显示的是在第18行运算时整型int型溢出了
int型: 在32/64位系统中都是32位,范围为-2147483648+2147483647,无符号情况下表示为04294967295。
这里运算的结果为2 666 274 961超了,但是还在无符号整型范围内
因此把题目中的状态数组改为无符号整型

class Solution {
public:
    int numDistinct(string s, string t) {
        int sn = s.length();
        int tn = t.length();
        if(tn == 0)return 1;
        if(sn == 0)return 0;
        vector<vector<unsigned int>>res(sn,vector<unsigned int>(tn,0));
        if(s[0] == t[0])res[0][0] = 1;
       // res[0][0] = s[0] == tn[0] ? 1 : 0;
        for(int i = 1; i < sn; i ++){
            res[i][0]+=res[i - 1][0];
            if(s[i] == t[0])res[i][0] ++;
        }
        for(int j = 1; j < tn; j ++){
            for(int i = j; i < sn; i ++){
                res[i][j] += res[i - 1][j];
                if(s[i] == t[j])res[i][j] =res[i - 1][j - 1] + res[i][j]; 
            }
        }       
        return res[sn - 1][tn - 1];
    }

};

通过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值