题解 | 判断子序列 + 力扣727.最短窗口子序列题解
判断子序列
https://www.nowcoder.com/practice/39be6c2d0a9b4c30a7b04053d5960a84
原题:判断子序列
,维护一个技术count,只要一次遍历T,T[i] = S[count],则计数+1,当计数长度和S相等,说明存在子串,直接返回。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param S string字符串
* @param T string字符串
* @return bool布尔型
*/
bool isSubsequence(string S, string T) {
// write code here
int count = 0;
for (int i = 0; i < T.length(); i++) {
if (T[i] == S[count]) {
count++;
}
if (count == S.length()) {
return true;
};
}
return false;
}
};
原题扩充
基于原题扩展到leetcode的 727.最短窗口子序列
给定字符串 S and T,找出 S 中最短的(连续)子串 W ,使得 T 是 W 的 子序列 。 如果 S 中没有窗口可以包含 T 中的所有字符,返回空字符串 ""。 如果有不止一个最短长度的窗口,返回开始位置最靠左的那个。 示例 1: 输入: S = "abcdebdde", T = "bde" 输出:"bcde" 解释: "bcde" 是答案,因为它在相同长度的字符串 "bdde" 出现之前。 "deb" 不是一个更短的答案,因为在窗口中必须按顺序出现 T 中的元素。
采用滑窗解法,虽然效率比不上动态规划,但是思路简单,为了避免超时,通过判断窗口左右边界是否是子串左右边界进行剪枝,可以减少不必要的窗口遍历。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param S string字符串
* @param T string字符串
* @return bool布尔型
*/
static bool compare(pair<int, string> a, pair<int, string> b) {
if (a.second.length() == b.second.length()) {
return a.first < b.first;
} else {
return a.second.length() < b.second.length();
}
}
string findMinSubstring(string S, string T) {
// write code here
int s_len = S.size();
int t_len = T.size();
int start = 0;
vector<pair<int, string>> ans;
for (size_t left = 0; left < t_len - s_len + 1; left++)
{
if (T[left] != S[0]) {
continue;
}
// 窗口右端点(不包含left + s_len自身) 至少从left + s_len开始, 不包含left + s_len自身
for (size_t right = left + s_len; right <= T.length(); right++)
{
if (T[right - 1] != S.back()) {
continue;
}
// sub_count: 子串有效长度计数
int sub_count = 0;
// 以idx为起点,遍历当前窗口
for (size_t idx = left; idx < right; idx++)
{
if (T[idx] == S[sub_count]) {
sub_count++;
}
// 找到子串
if (sub_count == s_len) {
string substring = T.substr(left, right - left);
ans.push_back(std::make_pair(left, substring));
}
}
}
}
if (ans.size() == 0) {
return "";
}
sort(ans.begin(), ans.end(), compare);
return ans[0].second;
}
};
找最短时用了排序算法,有点浪费性能,优化一下改成调用min算法:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param S string字符串
* @param T string字符串
* @return bool布尔型
*/
static bool compare(pair<int, string> a, pair<int, string> b) {
if (a.second.length() == b.second.length()) {
return a.first < b.first;
} else {
return a.second.length() < b.second.length();
}
}
string findMinSubstring(string S, string T) {
// write code here
int s_len = S.size();
int t_len = T.size();
int start = 0;
pair<int, string> ans = std::make_pair(T.size(), "");
for (size_t left = 0; left < t_len - s_len + 1; left++)
{
if (T[left] != S[0]) {
continue;
}
// 窗口右端点(不包含left + s_len自身) 至少从left + s_len开始, 不包含left + s_len自身
for (size_t right = left + s_len; right <= T.length(); right++)
{
if (T[right - 1] != S.back()) {
continue;
}
// sub_count: 子串有效长度计数
int sub_count = 0;
// 以idx为起点,遍历当前窗口
for (size_t idx = left; idx < right; idx++)
{
if (T[idx] == S[sub_count]) {
sub_count++;
}
// 找到子串
if (sub_count == s_len) {
string substring = T.substr(left, right - left);
pair<int, string> temp_ans = std::make_pair(left, substring);
if (ans.second == "") {
ans = temp_ans;
} else {
ans = std::min(ans, temp_ans, compare);
}
}
}
}
}
return ans.second;
}
};
