Minimum|Minimum Window Substring

问题 Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "".
The testcases will be generated such that the answer is unique.
A substring is a contiguous sequence of characters within the string.
Example 1:

Input: s = "ADOBECODEBANC", t = "ABC" Output: "BANC" Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.

Example 2:
Input: s = "a", t = "a" Output: "a" Explanation: The entire string s is the minimum window.

Example 3:
Input: s = "a", t = "aa" Output: "" Explanation: Both 'a's from t must be included in the window.

Since the largest window of s only has one 'a', return empty string.
Constraints:
  • m == s.length
  • n == t.length
  • 1 <= m, n <= 105
  • s and t consist of uppercase and lowercase English letters.
Follow up: Could you find an algorithm that runs in O(m + n) time?
Hint #1
Use two pointers to create a window of letters in S, which would have all the characters from T.
Hide Hint #2
Since you have to find the minimum window in S which has all the characters from T, you need to expand and contract the window using the two pointers and keep checking the window for all the characters. This approach is also called Sliding Window Approach.
L ------------------------ R , Suppose this is the window that contains all characters of T L----------------- R , this is the contracted window. We found a smaller window that still contains all the characters in TWhen the window is no longer valid, start expanding again using the right pointer.

解题思路 题中要求最好使用O(m + n)的时间复杂度来解决,所以Brute Force是行不通的。那么问题就来了,如何将嵌套循环优化为一次遍历?
这时候就该滑动窗口算法闪亮登场了。这个算法适合用来解决字符串/数组的子元素问题,可用来降低时间复杂度。抽象地说,整个字符串好比一个长长的推拉窗口,而这个窗口中间有两扇可移动的玻璃窗,我们可以这样做:
  1. 将一扇窗(右窗)从左端往右端移动
  2. 满足一定条件后,暂停移动右窗,将左窗从左端往右端移动
  3. 满足一定条件后,暂停移动左窗
  4. 重复上面的步骤,直到两扇窗移动到右边
回到本题, s 就是我们需要遍历的推拉窗,随着右窗的移动遍历 s 中的字符,暂停右窗的条件就是 t 中的字符都已出现,随着左窗移动,将 s 中的字符丢弃,当丢弃了 t 中的字符时,暂停左窗,继续右窗移动。
解体的关键在于
  1. 对字符串 t 建模,用数组或Map表示t中字符和出现的次数
  2. 遍历 s 时,当出现 t 中字符是,上述数组或Map的元素值-1,当元素值大于等于零时,表示有效计数
  3. 用计数器cnt表示 t 中字符出现的有效次数,当cnt==t.length时表示t中字符都已出现
  4. t 中字符都已出现后,开始移动左窗
参考答案
public String minWindow(String s, String t) { // 128 characters in ASCII int[] charCnt = new int[128]; int left = 0; int foundCharCnt = 0; int minLeft = -1; int minLen = Integer.MAX_VALUE; // loop t, charCnt++ when char appears in t for (char c : t.toCharArray()) { ++charCnt[c]; }// loop s for (int right = 0; right < s.length(); ++right) { // charCnt-- for each char, when char is in t (--charCnt >= 0) foundCharCnt++ if (--charCnt[s.charAt(right)] >= 0) { foundCharCnt++; } // when all chars in t have been found (foundCharCnt == t.length()) while (foundCharCnt == t.length()) { // record the minLen and minLeft if (minLen > right - left + 1) { minLen = right - left + 1; minLeft = left; } // if char at pointer left is in t (++charCnt > 0), foundCharCnt-- if (++charCnt[s.charAt(left)] > 0) { foundCharCnt--; } // shrink left pointer left++; } } return minLeft == -1 ? "" : s.substring(minLeft, minLeft + minLen); }

拓展训练 Given an array of integers of size ‘n’.
Our aim is to calculate the maximum sum of ‘k’
consecutive elements in the array.
Input: arr[] = {100, 200, 300, 400} k = 2 Output : 700

Input: arr[] = {1, 4, 2, 10, 23, 3, 1, 0, 20} k = 4 Output : 39 We get maximum sum by adding subarray {4, 2, 10, 23} of size 4.

Input: arr[] = {2, 3} k = 3 Output : Invalid There is no subarray of size 3 as size of whole array is 2.

详细解答参考下方链接
资料链接 【Minimum|Minimum Window Substring】原题
https://leetcode.com/problems...
滑动窗口算法
https://levelup.gitconnected....
拓展训练解答
https://www.geeksforgeeks.org...

    推荐阅读