题目描述:
标签:贪心算法 二分查找 动态规划
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
代码:
《一》动态规划
思路分析:动态规划五部曲
1、确定dp数组以及下标含义,dp[i][j]表示s字符串的前i-1个以及t字符串的前j-1个中最长重复子序列的长度
2、确定递推公式,如果s[i-1]==t[j-1],则dp[i][j]=dp[i-1][j-1]+1;否则,dp[i][j]=max(dp[i-1][j],dp[i][j-1])
3、dp数组初始化,dp[0][j]=dp[i][0]=0
4、确定遍历顺序,从前向后遍历,最后判断dp[n1][n2] == n1,如果相等返回true,否则返回false
5、举例推导dp数组
class Solution {
public boolean isSubsequence(String s, String t) {
int n1 = s.length();
int n2 = t.length();
int[][] dp = new int[n1+1][n2+1];
for(int i = 1;i <= n1;i++){
for(int j = 1;j <= n2;j++){
if(s.charAt(i-1) == t.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[n1][n2] == n1){
return true;
}else{
return false;
}
}
}
《二》双指针
思路分析:
1、定义双指针pre1和pre2指向两个字符串的开头;
2、遍历字符串,如果两个指针指向的元素相同则都++1,否则pre2++
3、判断pre1在循环结束后是否等于字符串s的长度,是的话返回true
class Solution {
public boolean isSubsequence(String s, String t) {
int pre1 = 0;
int pre2 = 0;
while(pre1 < s.length() && pre2 < t.length()){
if(s.charAt(pre1) == t.charAt(pre2)){
pre1++;
}
pre2++;
}
return pre1 == s.length();
}
}
《三》贪心算法
思路分析:
遍历s字符串,利用【indexOf(char c,index)——代表从index的位置后面开始寻找字符c的位置】方法找到每个字符出现的位置,直接从这个位置后面开始找,节省了很多寻找动作。
class Solution {
public boolean isSubsequence(String s, String t) {
int index = -1;
for(char c : s.toCharArray()){
index = t.indexOf(c,index+1);
if(index == -1){
return false;
}
}
return true;
}
}