子序列判断
- **题目:**给定字符串 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
-
- 最通俗易懂的解法:双指针
- 代码如下
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;
}
}
- 但是:最后挑战:
- 如果有大量输入的 S,称作S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
- 这个才是我们的最终目的!!! - 思路分析,有k个字符串或者说字串,要判断是否是T的子序列,
1.思路一:将T的所有子序列检索出来,如果用动态规划来求得的话,时间复杂度O(n),空间复杂度 O(T.length!);最后可能还需要一个集合或者树将所有序列存起来,方便检索;
2.思路二:题目给出字符串中只包含26个英文字母,那么只需要将26个字母存在一个集合或者 树当中,然后将对应的在T当中的索引存入,这样一来S可以直接通过索引存在与否,来判定是否是T的子序列;
字母 | a | b | … | y | z |
---|---|---|---|---|---|
链表 | 索引1,索引2,… | 索引 | … | 索引 | 索引 |
- 代码如下
//判断子序列,(进阶:有k个子序列,判断是否是T的子序列)
public static boolean isSubsequence(String s, String t) {
LinkedHashMap<Character,List<Integer>> list=new LinkedHashMap<>();
for (int i = 0; i < t.length(); i++) {
if(!list.containsKey(t.charAt(i))){
//若,字符不存在,将字符和索引都存入
List<Integer> al=new ArrayList<>();
al.add(i);
list.put(t.charAt(i),al);
}
else {
/*字符已经存在,将新的索引存入对应键下;*/
// list.put(t.charAt(i),i);
List<Integer>l= list.get(t.charAt(i));
l.add(i);
}
}
int p=-1;
for (int i = 0; i < s.length(); i++) {
//当前字符存在
if(list.containsKey(s.charAt(i))){
List<Integer>l= list.get(s.charAt(i));
Iterator<Integer> iter =l.iterator();
int k=p;
while (iter.hasNext()) {
int q = iter.next();
if (p < q) {
p = q;
break;
}
}
if(p==k)return false;
//找索引,大于p的,找不到返回flase;找到的话更新p,continue;
}
//不存在
else return false;
}
return true;
}
最终成功通过,对于这个题来说,效率并不是很高,但我们解决的是K的问题,早海量数据处理方面我们的代码优势还是很大的。