首先想到的就是利用动归,先从简单的开始,利用一个二维辅助数组 dp[i][j]
,表示 s.sub(0,i)
是否为 t.sub(0,j)
的子序列,其中有转换方程:
if (dp[i][j - 1]) dp[i][j] = true;
else dp[i][j] = dp[i - 1][j - 1] && (s.charAt(i) == t.charAt(j));
即如果 s.sub(0,i)
是 t.sub(0,j-1)
的子序列,则肯定也是 t.sub(0,j)
的子序列;否则,就需要看 s.sub(0,i-1)
是否为 t.sub(0,j-1)
的子序列,如果是的话就只要比较 s(i)
与 t(j)
是否相等,相等则 s.sub(0,i)
是 t.sub(0,j)
的子序列。
public static boolean isSubsequence(String s, String t) {
if (s == null || s.length() == 0) return true;
//该判断需要放在上一判断的后面,不然就要额外判断 t.length()==0 且 s.length()==0 的情况,此时应该是返回 true 的
if (t == null || t.length() == 0 || s.length() > t.length()) return false;
int len1 = s.length(), len2 = t.length();
boolean[][] dp = new boolean[len1][len2];
dp[0][0] = s.charAt(0) == t.charAt(0);
//第一排的需提前确定好,因为下面有涉及 dp[i-1]
for (int j = 1; j < len2; j++) {
//可能存在 s.chatAt(0) 与 t.chatAt(0) 不相等但是与 t.chatAt(j>0) 相等的情况
dp[0][j] = dp[0][j - 1] || s.charAt(0) == t.charAt(j);//
}
for (int i = 1; i < len1; i++) {
dp[i][i] = dp[i - 1][i - 1] && (s.charAt(i) == t.charAt(i));
}
for (int i = 1; i < len1; i++) {
for (int j = i + 1; j < len2; j++) {
if (dp[i][j - 1]) dp[i][j] = true;
else dp[i][j] = dp[i - 1][j - 1] && (s.charAt(i) == t.charAt(j));
//如果已经完整的判断了 s 字符串是 t 的子串,就没必要判断后面的了
if (i == len1 - 1 && dp[i][j]) return true;
}
}
return dp[len1 - 1][len2 - 1];
}
参考自 用时为 2 ms 的范例
该实现只需要 O(t.length())的时间复杂度,即只需要遍历 t.length() 的长度
public static boolean isSubsequence2(String s, String t) {
if (s == null || s.length() == 0) return true;
//该判断需要放在上一判断的后面,不然就要额外判断 t.length()==0 且 s.length()==0 的情况,此时应该是返回 true 的
if (t == null || t.length() == 0 || s.length() > t.length()) return false;
// index 用于遍历 s 的每个字符,看每一个字符是否按相对位置存在于 t 中
// 如果 s(i) 在 t(j) 的位置,则 s(i+1) 只需要从 t(j+1) 遍历比对
for(int index = 0,pos = 0; index < s.length(); index++,pos++){
pos = t.indexOf(s.charAt(index),pos);
if(pos == -1){
return false;
}
}
return true;
}
将
for(int index = 0,pos = 0; index < s.length(); index++,pos++){
pos = t.indexOf(s.charAt(index),pos);
if(pos == -1){
return false;
}
}
扩展即为:
int tPos = 0;
for (int i = 0; i < s.length(); i++) {
int j = tPos;
tPos=-1;
for (; j < t.length(); j++) {
if (s.charAt(i) == t.charAt(j)) {
tPos = j + 1;
break;
}
}
if (tPos == -1) return false;
}