判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"
是"abcde"
的一个子序列,而"aec"
不是)。
示例 1:
s =
"abc"
, t ="ahbgdc"
返回true
.
示例 2:
s =
"axc"
, t ="ahbgdc"
返回false
.
方法:双指针i,j,i指向短串s,j指向长串t
- s[i]=t[j],匹配i++,j++
- s[i]!=t[j] ,不匹配,用s[i]去匹配t[j]之后的元素,j++
如果i移动到了末尾,说明所有字符都匹配了
public boolean isSubsequence(String s, String t) {
int i=0;
int j=0;
while (i<s.length()&&j<t.length()){
if(s.charAt(i)==t.charAt(j)){
i++;
j++;
} else {
j++;
}
}
return i==s.length();
}
通过删除字母匹配到字典里最长单词
示例 1:
输入:s = "abpcplea", d = ["ale","apple","monkey","plea"]输出: "apple"
示例 2:
输入:s = "abpcplea", d = ["a","b","c"]输出: "a"
方法一:暴力回溯(超时)
public String findLongestWord(String s, List<String> d) {
StringBuilder sb=new StringBuilder();
findHelper(sb,s,d,0);
return ans;
}
private String ans="";
public void findHelper(StringBuilder sb,String s, List<String> d,int index){
if(index==s.length()){
String res=sb.toString();
if(d.contains(res)){
if (res.length() > ans.length() ||
(res.length() == ans.length() && res.compareTo(ans)<0)) {//注意字典序列
ans = res;
}
}
} else {
sb.append(s.charAt(index));//不删
findHelper(sb,s,d,index+1);
sb.deleteCharAt(sb.length()-1);//删
findHelper(sb,s,d,index+1);
}
}
方法二:转换成判断字典是否是串的子序列
因为要求返回最小的字典序列,所以需要先对字典排序
public String findLongestWord(String s, List<String> d) {
d.sort((o1, o2) -> o1.length() != o2.length() ? o2.length() - o1.length() : o1.compareTo(o2));
String ans = "";
for (String value : d) {
if (isSubsequence(value, s)) {
return value;
}
}
return ans;
}
public boolean isSubsequence(String s, String t) {
int i=0;
int j=0;
while (i<s.length()&&j<t.length()){
if(s.charAt(i)==t.charAt(j)){
i++;
j++;
} else {
j++;
}
}
return i==s.length();
}
方法三:在是子序列的时候再排序
public String findLongestWord(String s, List<String> d) {
String ans="";
for (String word:d){
if(isSubsequence(word,s)){
if(word.length()>ans.length()||(word.length()==ans.length()&&word.compareTo(ans)<0)){
ans=word;
}
}
}
return ans;
}