392. 判断子序列
题目链接:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"
是"abcde"
的一个子序列,而"aec"
不是)。
示例 1:
输入:s = "abc", t = "ahbgdc"
输出:true
示例 2:
输入:s = "axc", t = "ahbgdc"
输出:false
提示:
-
0 <= s.length <= 100
-
0 <= t.length <= 10^4
-
两个字符串都只由小写字符组成。
解题思路
本题最直接的方法就是用“双指针”来解决,时间复杂度为O(N)
,N
是t
的长度。
此处我们采用动态规划来解答,其实这道题虽说是判断t
字符串是不是s
字符串的子序列,但也可以按照
不过,为了体现“字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串”,也就是考虑“删除”,递推公式可以发生一些变化。
C++
class Solution { public: bool isSubsequence(string s, string t) { if (s.size() == 0) return true; if (s.size() > t.size()) return false; // 1. dp数组的含义 // dp[i][j] 表示以下标i - 1为结尾的 s,和以下标j - 1为结尾的 t,相同子序列的最大长度 // 3. 初始化 vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1 , 0)); // 4. 遍历顺序,从上到下,从左到右 for (int i = 1; i <= s.size(); i++) { for (int j = 1; j <= t.size(); j++) { // 2. 递推公式 // 如果s[i - 1] 等于 t[j - 1],也就是找到了一个相同的字符,相同子序列长度自然要在dp[i-1][j-1]的基础上加1 if (s[i - 1] == t[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { // dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); // 如果s[i - 1] 不等于 t[j - 1],此时相当于t要删除元素,t如果把当前元素t[j - 1]删除 // 那么dp[i][j] 的数值就是 s[i - 1]与 t[j - 2]的比较结果(dp[i][j - 1]) dp[i][j] = dp[i][j - 1]; } } } if (dp[s.size()][t.size()] == s.size()) return true; else return false; } };
JavaScript
/** * @param {string} s * @param {string} t * @return {boolean} */ var isSubsequence = function(s, t) { const dp = Array(s.length + 1).fill().map(item => Array(t.length + 1).fill(0)); for (let i = 1; i <= s.length; i++) { for (let j = 1; j <= t.length; j++) { if (s[i - 1] === t[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = dp[i][j - 1]; } } } return s.length === dp[s.length][t.length]; };
-
时间复杂度:O(n × m)
-