leetcode 76. 最小笼罩子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
留神:
对于 t 中反复字符,咱们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,咱们保障它是惟一的答案。示例 1:
输出:s = "ADOBECODEBANC", t = "ABC"
输入:"BANC"
应用两个哈希表,ht存字符串t的字符呈现次数。而后遍历字符串s,当某个字符次数还未到t中的次数,则示意该字符是无效字符[可用于笼罩t]。
双指针算加须要指针具备枯燥性,这样工夫复杂度能力为O(n)。
枯燥性证实:假如[j, i]之间的字符为涵盖t的一段,则当i往后走到i',[j, i']必定也涵盖了t。此时j也只能往后走,因为要求的是最小子串。
什么时候j能够往后走:当s[j]呈现次数大于
t中的次数时,阐明即便没有s[j],[j, i]中也至多有了ht[s[j]]个s[j]了,故此时曾经不须要j地位字符。
unordered_map<char, int> hs, ht;string minWindow(string s, string t) { for (char c : t) ht[c]++; string ans; for (int i = 0, j = 0, cnt = 0; i < s.size(); i++) { hs[s[i]]++; if (hs[s[i]] <= ht[s[i]]) cnt++; while (hs[s[j]] > ht[s[j]]) // 不能是>=,因为只有当该字符在hs中冗余了,能力将该字符略过 hs[s[j++]]--; if (cnt == t.size()) { if (ans.empty() || i - j + 1 < ans.size()) ans = s.substr(j, i - j + 1); } } return ans;}
leetcode 3. 无反复字符的最长子串
给定一个字符串 s ,请你找出其中不含有反复字符的 最长子串 的长度。
示例 1:
输出: s = "abcabcbb"
输入: 3
解释: 因为无反复字符的最长子串是 "abc",所以其长度为 3。
指针枯燥性证实[反证]:假如[j, i]为以后无反复字符最长子串,则当i向后走到i'时,如果此时j往前走,[j', i]必定蕴含反复字符,不符题意。故当i往后,j也只能往后走。
什么时候j能够往后走:当新加进来的i字符反复了,此时就须要让j往后走,直到[j, i]无反复字符。
int lengthOfLongestSubstring(string s) { unordered_map<char, int> hmap; int ans = 0; for (int i = 0, j = 0; i < s.size(); i++) { hmap[s[i]]++; while (hmap[s[i]] > 1) hmap[s[j++]]--; ans = max(ans, i - j + 1); } return ans;}