题目描述:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"
是"abcde"
的一个子序列,而"aec"
不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
示例 1:
输入:s = "abc", t = "ahbgdc" 输出:true
示例 2:
输入:s = "axc", t = "ahbgdc" 输出:falses
思路一:
要判断字符串 s
是否为字符串 t
的子序列,我们可以遍历 t
,每次在 t
中查找 s
当前字符的索引。如果找到了,我们更新 s
的索引,继续查找下一个字符;如果遍历完 t
后 s
也遍历完毕,那么 s
就是 t
的子序列。
代码实现:
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isSubsequence = function (s, t) {
let indexS = 0; // s 的当前索引
let indexT = 0; // t 的当前索引
while (indexS < s.length && indexT < t.length) {
// 如果当前字符匹配,则移动 s 的索引
if (s[indexS] === t[indexT]) {
indexS++;
}
// 无论如何都移动 t 的索引
indexT++;
}
// 如果 s 完全遍历完毕,说明 s 是 t 的子序列
return indexS === s.length;
};
思路二:
使用两个指针 U
和 D
来遍历字符串 s
和 t
。如果 s
中的每个字符都能在 t
中按顺序找到,那么 t
就是 s
的子序列。如果遍历完 s
后 found
仍然为 true
,则返回 true
,否则返回 false
。
代码实现:
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isSubsequence = function (s, t) {
const n1 = s.length, n2 = t.length;
let U = 0, D = 0; // U 指向 s 的当前字符,D 指向 t 的当前字符
let found = true; // 假设 t 是 s 的子序列
for (let i = 0; i < n1; i++) { // 遍历 s
while (D < n2 && s[i] !== t[D]) { // 寻找 s[i] 在 t 中的位置
D++; // 如果当前 t[D] 不匹配,继续向后查找
}
if (D === n2) { // 如果到达 t 的末尾还没有找到 s[i],则 t 不是 s 的子序列
found = false;
break;
}
D++; // 找到匹配的字符后,D 向前移动
}
return found;
};