版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
题目:leetcode 392
给定字符串 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.
后续挑战 :
如果有大量输入的 S,称作S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
第一次解法,想太复杂了
class Solution {
//有利条件是仅包含小写字母 26个,这道题目本质是求解字母间(排列)关系
//O(n)神作,我在leetcode第一个原创
class Pair {
final String str = "abcdefghijklmnopqrstuvwxyz";
char x;
char y;
Pair(char x, char y) {
this.x = x;
this.y = y;
}
Pair(int pos) {
this.x = str.charAt(pos/26);
this.y = str.charAt(pos%26);
}
int getPos() { //获取一个字符对对应的小标
return (this.x-'a')*26 + (this.y-'a');
}
}
public boolean isSubsequence(String s, String t) {
if (s.length() == 1) return t.contains(s);
int[] slots = new int[26*26];
//设置判断用的数组
for (int i=0; i<slots.length; i++) {
Pair pair = new Pair(i);
if (isExistPair(t, pair)) slots[i] = 1;
}
//循环一遍检查s是否符合要求
for (int i=1; i<s.length(); i++) {
Pair pair = new Pair(s.charAt(i-1), s.charAt(i));
int pos = pair.getPos();
if (slots[pos] == 0) return false;
}
return true;
}
private boolean isExistPair(String t, Pair pair) {
int start = 0;
int end = t.length()-1;
while (start < end) {
if (t.charAt(start) == pair.x && t.charAt(end) == pair.y) {
return true;
} else if (t.charAt(start) == pair.x && t.charAt(end) != pair.y){
end--;
} else if (t.charAt(start) != pair.x && t.charAt(end) == pair.y){
start++;
} else {
start++;
end--;
}
}
return false;
}
}
而且是错的,比如leeeeetcode,ee关系是存在,但是t中只有4个e,我也判断是对的,因为这里我没有次数信息,只有这对Pair关系是否存在的标记
第二次用快慢指针,形象,而且对了
class Solution {
//快慢指针O(n)搞定;慢指针对s,快指针对t,慢走完了,但是t没有溢出就是true
public boolean isSubsequence(String s, String t) {
if ("".equals(t)) {
if ("".equals(s)) return true;
else return false;
}
int slow = 0;
int fast = 0;
while (slow < s.length()) {
if (fast >= t.length()) return false;
if (s.charAt(slow) != t.charAt(fast)) {
fast++;
} else {
slow++;
fast++;
}
}
return true;
}
}