(1)
双指针法
class Solution {
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 ++;
}
return i == s.length();
}
}
二分法
public boolean isSubsequence(String s, String t) {
List<Integer>[] list = new ArrayList[26];
for (int i = 0; i < t.length(); i ++) {
int idx = t.charAt(i) - 'a';
if (list[idx] == null)
list[idx] = new ArrayList<>();
// 添加索引坐标 进去 时间复杂度 O(n)
list[idx].add(i);
}
//
int j = 0;
for (int i = 0 ; i < s.length(); i ++) {
int idx = s.charAt(i) - 'a';
// 按顺序 返回匹配位置的最小坐标
if (list[idx] == null) return false;
int nearL = nearL(list[idx] , j);
if (nearL == -1) return false;
j = list[idx].get(nearL) + 1;
}
return true;
}
private int nearL(List<Integer> list , int q) {
int i = 0 ;
int j = list.size() - 1;
int ans = -1;
while (i <= j) {
int mid = i + ((j - i) >> 1);
if (list.get(mid) >= q ) {
ans = mid;
j = mid - 1;
}
else {
i = mid + 1;
}
}
System.out.println(ans);
System.out.println("target " + q);
return ans;
}
进阶
(2)
二分法
class Solution {
public int numMatchingSubseq(String s, String[] words) {
List<Integer>[] idx = new ArrayList[26];
// 预处理 存储该字符出现的位置
for (int i = 0 ; i < s.length() ; i ++) {
int index = s.charAt(i) - 'a';
if (idx[index] == null) idx[index] = new ArrayList<>();
idx[index].add(i);
}
// 记录答案
int ans = 0;
for (String t : words) {
// t 匹配 s
int j = 0;
boolean flag = true;
for (int i = 0 ; i < t.length() ; i ++) {
int index = t.charAt(i) - 'a';
if (idx[index] == null) {
flag = false;
break;
};
int pos = nearL(idx[index],j);
if (pos == -1) {
flag = false;
break;
}
j = idx[index].get(pos) + 1;
}
if (flag == true) ans ++;
}
return ans;
}
private int nearL(List<Integer> list , int target) {
int l = 0 , r = list.size() - 1,ans = -1;
while (l <= r) {
int mid = l + ((r - l) >> 1);
if (list.get(mid) >= target) {
ans = mid;
r = mid - 1;
}else {
l = mid + 1;
}
}
return ans;
}
}