392.判断子序列
392.判断子序列
题目
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
致谢:
特别感谢 @pbrother 添加此问题并且创建所有测试用例。
示例 1:
输入:s = "abc", t = "ahbgdc"
输出:true
示例 2:
输入:s = "axc", t = "ahbgdc"
输出:false
提示:
0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/is-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解1-指针
定义一个指向s的指针sp,遍历t字符串,如果s.charAt(sp) == ts.charAt(i),说明当前元素相等,sp++,如果最后sp==s.length()说明s是t的子序列
class Solution {
public boolean isSubsequence(String s, String t) {
int sLen = s.length();
int tLen = t.length();
if(sLen==0)return true;
if(sLen>tLen)return false;
int sp = 0;
for(int i=0;i<tLen;i++){
if(s.charAt(sp) == t.charAt(i)){
sp++;
if(sp==sLen)return true;
}
}
return false;
}
}
这里还可以优化为双指针
题解2-动态规划
要学会已知推未知,把学过的东西用起来
如果s是t的子序列,那么s和t的最长公共子序列就是s的长度。
dp[i][j]表示以i-1结尾的字符串与j-1结尾的字符串的最长公共子序列的长度为dp[i][j]
dp[i][j]可以由两个方案推出
如果text1.charAt(i-1) == text2.charAt(j-1),则dp[i][j] = dp[i-1][j-1] + 1
如果text1.charAt(i-1) ≠ text2.charAt(j-1),两个字符串的最后一位不相等,那么字符串text1的[0,i-1]区间和字符串text2的[0,j-1]区间的最长公共子序列长度无法延长,因此dp[i][j]就会继承dp[i-1][j]与dp[i][j-1]中的较大值,dp[i][j]=Math.max(dp[i][j-1],dp[i-1][j])
这里思考还是得围绕递推式主旨如何到这一步?选择哪种走法?
因为有两种路径可以到这一步,一个是text1的[0,i-2]text2的[0,j-1],i在走一步;一个是text1的[0,i-1]text2的[0,j-2],j在走一步
class Solution {
public boolean isSubsequence(String s, String t) {
int len1=s.length();
int len2=t.length();
int dp[][] = new int[len1+1][len2+1];
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(text1.charAt(i-1) == text2.charAt(j-1))
dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j]=Math.max(dp[i][j-1],dp[i-1][j]);
if(dp[i][j]==len1) return true;
}
}
return false;
}
}
空间优化
发现dp[i][j]只与三个位置有关dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]
class Solution {
public boolean isSubsequence(String s, String t) {
int sLen = s.length();
int tLen = t.length();
if(sLen==0)return true;
if(sLen>tLen)return false;
int dp[] = new int[tLen+1];
int last = 0;
int tmp = 0;
for(int i=1;i<=sLen;i++){
last =dp[0];
for(int j=1;j<=tLen;j++){
tmp=dp[j];
if(s.charAt(i-1) == t.charAt(j-1)){
dp[j] = last + 1;
}
else dp[j]=Math.max(dp[j-1],dp[j]);
last =tmp;
if(dp[j]==sLen) return true;
}
}
return false;
}
}