跳至主要內容

392. 判断子序列


392. 判断子序列

🟢   🔖  双指针 字符串 动态规划  🔗 力扣open in new window LeetCodeopen in new window

题目

Given two strings s and t, return true ifs _is a subsequence of _t , orfalse otherwise.

A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., "ace" is a subsequence of " _a_ b _c_ d _e_ " while "aec" is not).

Example 1:

Input: s = "abc", t = "ahbgdc"

Output: true

Example 2:

Input: s = "axc", t = "ahbgdc"

Output: false

Constraints:

  • 0 <= s.length <= 100
  • 0 <= t.length <= 10^4
  • s and t consist only of lowercase English letters.

Follow up: Suppose there are lots of incoming s, say s1, s2, ..., sk where k >= 109, and you want to check one by one to see if t has its subsequence. In this scenario, how would you change your code?

题目大意

给定字符串 st ,判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace""abcde"的一个子序列,而"aec"不是)。

进阶 :如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

解题思路

思路一:双指针

  • 使用两个指针 ij,分别遍历 st
    1. 指针 i 用于指向 s 中的当前字符;
    2. 指针 j 用于指向 t 中的当前字符。
  • 遍历 t
    • 如果 s[i] == t[j],说明匹配上了,i++
    • 始终移动 j,以确保字符的顺序性。
  • 如果 i == s.length,说明 s 的所有字符都能按顺序匹配上,返回 true;否则返回 false

复杂度分析

  • 时间复杂度: O(n),其中 n 是字符串 t 的长度。
  • 空间复杂度: O(1)

进阶:二分法(进阶版)

  • 预处理 t 的索引位置

    • 先用一个哈希表 indexMap 存储 t 中每个字符的所有出现位置(按照索引升序)。
  • 二分查找加速匹配

    • 遍历 s 中的每个字符,使用二分查找定位该字符在 t 中的下一个匹配位置。
    • 在哈希表中,快速找到 t 中大于当前指针 j 的最小索引。
    • 如果找不到,说明无法匹配当前字符,返回 false
  • 二分查找函数 left_bound:在升序数组中找到第一个大于等于 target 的位置,若不存在返回 -1

复杂度分析

  • 时间复杂度: O(n + m log n),其中 n 是字符串 t 的长度,ms 的长度。

    • 预处理:遍历 t 构建哈希表,时间复杂度为 O(n)
    • 匹配:对于每个字符,在哈希表中查找位置,时间复杂度为 O(m log n)
    • 总复杂度: O(n + m log n)
  • 空间复杂度: O(n),使用一个哈希表存储索引位置。

代码

双指针
/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isSubsequence = function (s, t) {
	let i = 0; // 指向 s 的指针
	let j = 0; // 指向 t 的指针
	while (i < s.length && j < t.length) {
		if (s[i] == t[j]) {
			i++; // 匹配上时移动 s 的指针
		}
		j++; // 始终移动 t 的指针
	}
	return i == s.length; // 是否完全匹配
};

相关题目

题号标题题解标签难度力扣
792匹配子序列的单词数字典树 数组 哈希表 4+🟠🀄️open in new window 🔗open in new window
1055形成字符串的最短路径 🔒贪心 双指针 字符串 1+🟠🀄️open in new window 🔗open in new window
2486追加字符以获得子序列贪心 双指针 字符串🟠🀄️open in new window 🔗open in new window
2825循环增长使字符串子序列等于另一个字符串[✓]双指针 字符串🟠🀄️open in new window 🔗open in new window