剑指 Offer II 017. 含有所有字符的最短字符串
给定两个字符串 s 和 t 。返回 s 中包含 t 的所有字符的最短子字符串。如果 s 中不存在符合条件的子字符串,则返回空字符串 "" 。
如果 s 中存在多个符合条件的子字符串,返回任意一个。
注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最短子字符串 "BANC" 包含了字符串 t 的所有字符 'A'、'B'、'C'
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入:s = "a", t = "aa"
输出:""
解释:t 中两个字符 'a' 均应包含在 s 的子串中,因此没有符合条件的子字符串,返回空字符串。
提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
解析:
双指针,
vis1统计t中每个字符的个数
vis2统计s中遍历到i时每个字符的个数,
如果vis2中每个字符的个数大于等于vis1,则记录当前长度和起点终点(如果当前长度小于maxLen的话)
并起点向后走,如果仍然符合上述条件,则更新最大长度,记录起点终点,直至不符合上述条件
r向后走
class Solution { public: bool check(const vector<int>& vis1, const vector<int>& vis2) { for(int j = 0; j < 58; j++) { if(vis2[j] < vis1[j]) { return false; } } return true; } string minWindow(string s, string t) { int n = s.length(); int m = t.length(); if(m > n) return ""; int cnt = 100010, x = 0, y = 0; vector<int> vis1(58, 0), vis2(58, 0); for(int i = 0; i < m; i++) { vis1[t[i] - 'A']++; } int l = 0; for(int i = 0; i < n; i++) { vis2[s[i] - 'A']++; while(check(vis1, vis2)) { if(i - l + 1 < cnt) { cnt = i - l + 1; x = l, y = i; } vis2[s[l] - 'A']--; l++; } } if(cnt == 100010) return ""; string ret = ""; for(int i = x; i <= y; i++) ret += s[i]; return ret; } };
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。