LeetCode | Distinct Subsequences(不同的子序列)
2014-08-14 21:38
295 查看
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 relative positions of the remaining characters. (ie,
a subsequence of
not).
Here is an example:
S =
Return
题目解析:
S串通过删减元素能形成多少中T串。其相对位置不能改变。
方案一:
通过DFS来求解,当s[i] == t[j]的时候,我们可以选择s[i]深层次递归,也可以不选择s[i]深层次递归。但是会出现超时结果。
方案二:
像这种递归超时的情况,可尝试用动态规划来求解。
动态规划难就难在找递推关系上。没有一个正确的方法,就会陷到死角去。
问1:当s[i]和t[j]不相等的时候,t[j]要和s[i]以后的比较。
答:这种思维就错误了,我们用DFS的时候,是上面这种思路,但是动态规划,是将大问题化渐成小问题。因此当s[i]和t[j]不相等的时候,t[j]要和s[i]以后的比较,并且只利用与s[i-1]的比较结果就行了,不需要再往前找。因为当我们求解二维数组的时候,已经求解出了t[j]和s[i-2]等的关系。
如果不好想的话,就那t[m]和s
比较,当两个不相等的时候,就没有s[n+1]了,应该向前找。
问2:递推关系式是什么?
那就考察s[i]和t[j]相等和不相等的情况。
把这个递推条件设为S前i个字符通过删除字符得到T前j个字符的转换方法,用二维数组元素transArr[i][j]记录。
(1)若S[i]==T[j],说明把S[i]、T[j]分别加入S[0~i-1]和T[0~j-1]可以完全复制transArr[i-1][j-1]种转换方式。另外,S[0~i-1]本身(无需加入S[i])也能以transArray[i-1][j]种方式转换为T[0~j]。
transArr[i][j] = transArr[i-1][j-1]+transArr[i-1][j];
(2)若S[i]!=T[j],说明S[i]无法用于转换为T[0~j],T[j]需要从S[0~i-1]中获取,因此S[0~i]与S[0~i-1]无异。
transArr[i][j] = transArr[i-1][j];
有了这两个关系式,才能进行下一步的计算。
问3:边界条件是什么?
递推关系一定要有个其实值,不然求解的时候,就没法向后延伸。我们思考下,当T为空串的时候,S为任意长度,那么删除S所有元素,就能变成T了。也就是边界条件为1。
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).
Here is an example:
S =
"rabbbit", T =
"rabbit"
Return
3.
题目解析:
S串通过删减元素能形成多少中T串。其相对位置不能改变。
方案一:
通过DFS来求解,当s[i] == t[j]的时候,我们可以选择s[i]深层次递归,也可以不选择s[i]深层次递归。但是会出现超时结果。
class Solution { public: int numDistinct(string S, string T) { CountDistinct(S,0,T,0); return count; } void CountDistinct(string S,int index1,string T,int index2){ if(index2 >= T.size()){ count++; return; } //找到等于T[index2]的点。但在循环中一定要添加变量范围限制 while(index1 < S.size() && S[index1] != T[index2]) index1++; if(index1 >= S.size()) return; CountDistinct(S,index1+1,T,index2+1);//选择这个点 CountDistinct(S,index1+1,T,index2); //不选这个点 } private: int count = 0; };
方案二:
像这种递归超时的情况,可尝试用动态规划来求解。
动态规划难就难在找递推关系上。没有一个正确的方法,就会陷到死角去。
问1:当s[i]和t[j]不相等的时候,t[j]要和s[i]以后的比较。
答:这种思维就错误了,我们用DFS的时候,是上面这种思路,但是动态规划,是将大问题化渐成小问题。因此当s[i]和t[j]不相等的时候,t[j]要和s[i]以后的比较,并且只利用与s[i-1]的比较结果就行了,不需要再往前找。因为当我们求解二维数组的时候,已经求解出了t[j]和s[i-2]等的关系。
如果不好想的话,就那t[m]和s
比较,当两个不相等的时候,就没有s[n+1]了,应该向前找。
问2:递推关系式是什么?
那就考察s[i]和t[j]相等和不相等的情况。
把这个递推条件设为S前i个字符通过删除字符得到T前j个字符的转换方法,用二维数组元素transArr[i][j]记录。
(1)若S[i]==T[j],说明把S[i]、T[j]分别加入S[0~i-1]和T[0~j-1]可以完全复制transArr[i-1][j-1]种转换方式。另外,S[0~i-1]本身(无需加入S[i])也能以transArray[i-1][j]种方式转换为T[0~j]。
transArr[i][j] = transArr[i-1][j-1]+transArr[i-1][j];
(2)若S[i]!=T[j],说明S[i]无法用于转换为T[0~j],T[j]需要从S[0~i-1]中获取,因此S[0~i]与S[0~i-1]无异。
transArr[i][j] = transArr[i-1][j];
有了这两个关系式,才能进行下一步的计算。
问3:边界条件是什么?
递推关系一定要有个其实值,不然求解的时候,就没法向后延伸。我们思考下,当T为空串的时候,S为任意长度,那么删除S所有元素,就能变成T了。也就是边界条件为1。
class Solution { public: int numDistinct(string S, string T) { if(S.size() < T.size() || T.size() == 0) return 0; int **arr = new int*[S.size()+1]; for(int i = 0;i <= S.size();i++) arr[i] = new int[T.size()+1]; for(int i = 0;i <= T.size();i++) arr[0][i] = 0; for(int i = 0;i <= S.size();i++) arr[i][0] = 1; for(int i = 1;i <= S.size();i++){ for(int j = 1;j <= T.size();j++){ if(S[i-1] == T[j-1]) //数组中和字符串中坐标不一致,应小心 arr[i][j] = arr[i-1][j-1]+arr[i-1][j]; else arr[i][j] = arr[i-1][j]; } } return arr[S.size()][T.size()]; } };
相关文章推荐
- [LeetCode] Distinct Subsequences 不同的子序列
- Leetcode 115 Distinct Subsequences(不同的子序列)
- LeetCode 62. Unique Paths(所有不同的路径)
- leetcode-两个不同字符串
- LeetCode刷题记录5-计算有序数组不同项的个数
- LeetCode 96. Unique Binary Search Trees Python Solution, Catalan数 结点数为n的不同形态的二叉树一共有多少种
- Leetcode 392. Is Subsequence 判断子序列 解题报告
- LeetCode关于找不同的解法
- [LeetCode] 241. Different Ways to Add Parentheses 添加括号的不同方式
- [LeetCode] Different Ways to Add Parentheses 加括号的不同方式
- LeetCode 63. Unique Path II(所有不同路径之二)
- LeetCode题库解答与分析——#95. 不同的二叉查找树 IIUniqueBinarySearchTreeII
- [LeetCode] Is Subsequence 判断一个字符串是否为另一个的子序列
- LeetCode --- 62. 不同路径
- LeetCode 334. Increasing Triplet Subsequence(长度为3的递增子序列)
- [LeetCode] Is Subsequence 是子序列
- leetcode 相同字母组成的不同单词归为一类即所谓的变位词
- [LeetCode] Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串
- [LeetCode] 159. Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串
- Leetcode 389. Find the Difference 找不同 解题报告