Given a string s and a string t, check if s is subsequence of t.
You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not).
Example 1:
s = "abc", t = "ahbgdc"
Return true.
Example 2:
s = "axc", t = "ahbgdc"
Return false.
Follow up:
If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
Solution1:Two pointers
思路:
Time Complexity: O(s.len + t.len) Space Complexity: O(1)
Solution2:Binary Search
For follow up: 如果t很长的话 且 很对不同s多次调用,可以使用这种方法先建立buildTPosMap,会快。
Time Complexity: O(s.len * log(t.len)) Space Complexity: O(1)
思路: 对t建立一个hashmap,是每个字符 -> 该字符所有位置组成list 的map。拿到s后,遍历s的每个字符,在map对应字符的位置list中,二分查找得到最近的可用位置,最近可用意味着是在前一个字符得到的位置之后(变量prev)的最近位置。(list一定是递增的,所以可以利用二分查找)
Solution1 Code:
class Solution1 {
public boolean isSubsequence(String s, String t) {
if (s.length() == 0) return true;
int index_s = 0, index_t = 0;
while (index_t < t.length()) {
if (t.charAt(index_t) == s.charAt(index_s)) {
index_s++;
if (index_s == s.length()) return true;
}
index_t++;
}
return false;
}
}
Solution2 Code:
class Solution2 {
private List<Integer>[] t_pos_map = new List[256];
public boolean isSubsequence(String s, String t) {
buildTPosMap(t);
int prev = 0;
for (int i = 0; i < s.length(); i++) {
if (t_pos_map[s.charAt(i)] == null) return false;
int j = Collections.binarySearch(t_pos_map[s.charAt(i)], prev);
if (j < 0) j = -j - 1;
if (j == t_pos_map[s.charAt(i)].size()) return false;
prev = t_pos_map[s.charAt(i)].get(j) + 1;
}
return true;
}
private void buildTPosMap(String t) {
for (int i = 0; i < t.length(); i++) {
if (t_pos_map[t.charAt(i)] == null)
t_pos_map[t.charAt(i)] = new ArrayList<>();
t_pos_map[t.charAt(i)].add(i);
}
}
}