原题:判断子序列
,维护一个技术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; } };