Leetcode 115 Distinct Subsequences 解题报告
2015-09-09 10:46
756 查看
Distinct Subsequences
Total Accepted: 38466 Total Submissions: 143567My SubmissionsQuestion Solution
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,
"ACE"is a subsequence of
"ABCDE"while
"AEC"is not).
Here is an example:
S =
"rabbbit", T =
"rabbit"
Return
3.
首先要读懂题意。题目中“count the number of distinct subsequences of T in S.” sequence是序列的意思,subqequence就是子序列。我们知道序列是由一个个元素排列而成。所以,题目中的“字符串T”为“字符串S”的子序列。求“字符串S”中“子序列字符串T”的个数,也就变形为:取出“字符串S”中的若干元素,顺序排列,组成“字符串T”,有多少种取法?
我认为上述分析思路比题目中提到的“删除元素”的思路要好。因为当T和S长度相近时,两种思路效率差不多;当S远大于T时,由于组成一次“字符串T”要删除非常多的元素,显然,效率远低于第一种思路。
参考 Rachel Zhang 的解题报告,同样的,我具体用了两种不同的方法去解这个题。
方法一:迭代+递归,具体思路是深度优先搜索(Depth First Search),但无法通过,因为TLE(Time Limit Exceeded)
以字符串S=“PabZcdefSghZijZkSlmZnoPqrStuZvwSxZyZ” ,字符串T=“PSZ”为例。
为了方便大家观察,我把'P'、'S'、'Z'在字符串S中的位置着重标出来。
S中元素'P'的位置=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
S中元素'S'的位置=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
S中元素'Z'的位置=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
观察字符串。字符串中任意的元素'P'、'S'、'Z',如果以顺序排列,则组成满足条件的字符串S"PSZ"。
那么我们如何保证在取'P'、'S'、'Z'的时候既是顺序排列,又不多取,不少取呢?
显然,用DFS就可以做到。
下面为不熟悉DFS的朋友具体讲个例子,高手可以直接跳过。
Eg:
先找字符串S中有几个'P',2个: 0, 23
对位置为0的字符‘P’,其后面有几个'S',4个:8,16,25,31
对位置为8的字符'S',其后面有几个'Z',6个:11,14,19, 28, 33, 35
所以'0 8 11', '0 8 14 ', '0 8 19', '0 8 28', '0 8 28', '0 8 33', '0 8 35'都是subsequence“PSZ”。
依次再遍历'0 16 X'、'0 25 X'的情况,依次类推。非常明显,这个例子就是“深度优先的”。
以下是代码:
class Solution(object): def numDistinct(self, s, t): """ :type s: str :type t: str :rtype: int """ num=[0] self.CountSubsequence(s,t,0,0,num) return num[0] def CountSubsequence(self,father_sequence,child_sequence,index_father,index_child,num): #print(index_father,index_child) len_father=len(father_sequence) len_child=len(child_sequence) if index_child==len_child: num[0]+=1 #print("匹配到了相同的") else: #print("进入迭代") for i in range(index_father,len_father): if father_sequence[i]==child_sequence[index_child]: self.CountSubsequence(father_sequence,child_sequence,i+1,index_child+1,num) #这里num是一个列表,可以从外部访问的,所以不需要return
方法二:DP(Dynamic Programming, 动态规划)
此处参考陆草纯的解题报告将问题转化为“二维地图走法问题”。
我觉得他在文章里对转化为“二维地图走法问题”说明的不清楚:
疑问一:为何走的时候只能“对角线走”和“向右向下走”,不能“向下向右走”。
疑问二:为何字符判断相等时,是“对角线走”和“向右向下走”相加;而字符不等时,只能“向右向下走”。
经过自己的思考,我来说一下我的理解:
一个子字符串t',一个父字符串s',两者一点一点相加。最终子字符串的长度加到T的长度,父字符串的长度加到S的长度。
当字符不等时,也就是说,父字符串s‘中新加的元素s'[i]无法对走法有贡献,所以可以删掉,于是就变成了“向右向下走”
字符相等时,父字符串s'中新加的元素s'[i]对走法有贡献,所以对角线是可以取的;同时“向右向下走”(即删掉s'[i])也是可行的;由于两者是不同的走法,自然要相加。
显然,DP的思路是从0开始一点一点增加子字符串的长度,最终达到我们想要匹配的字符串长度。显然不能减少字符串t'的长度。
大家画个图就明白了,以s' 为纵轴,t'为横轴。下面直接上AC的python代码:
class Solution(object): def numDistinct(self, s, t): """ :type s: str :type t: str :rtype: int """ #s is father_sequence #t is child_sequence len_father=len(s) len_child=len(t) dp=[[0 for i in range(len_child)] for j in range(len_father)] if len_father==0 or len_child==0: result=0 else: #dp=[[0 for i in range(len_child)] for j in range(len_father)] if s[0]==t[0]: dp[0][0]=1 for i in range(1,len_father): dp[i][0]=dp[i-1][0] if s[i]==t[0]: dp[i][0]+=1 for i in range(1,len_father): for j in range(1,len_child): if i>=j: if s[i]==t[j]: dp[i][j]=dp[i-1][j-1]+dp[i-1][j] else: dp[i][j]=dp[i-1][j] result=dp[len_father-1][len_child-1] return result
相关文章推荐
- iOS UINavigationController与UITabBarController的组合使用
- 开源项目分析之UIL(续)
- UICollectionView 高级进阶篇
- Java build模式
- iOS 提交代码出现提示弹出框显示 “A commit message is required to perform this operation.Enter a commit message and try again.“
- JSP页面中的标签以及内置对象request等
- 解决pycharm无法提示pyqt4.QtGui但是可以运行的问题
- 关于easyui的datagrid detailview的初次点击出现的重叠错位问题
- EasyUI基础知识Draggable(拖累)
- 关于使用xcconfig定制化build设置
- SharePoint 2013 Installation and Configuration Issues
- 【Android】 ProcessBuild Process su 命令
- UIView Animation 与 CACoreAnimation
- [Android fix] java.exe finished with non-zero exit value 2
- UINavigationController 返回上一级,返回根控制器,返回某一级
- iOS开发-------选择器(UIPickView)
- 如何使用Xcode分析调试在真机运行的UE4 IOS版游戏
- UI:页面传值、单例模式传值、属性传值、NSUserDefaults 数据持久化
- juicer
- 根据字符串长度计算UILabel的高度