LeetCode 76. Minimum Window Substring

寻找最小覆盖子串的高效算法
本文介绍了一种寻找字符串中最小覆盖子串的方法,适用于复杂度为O(n)的场景。通过构建字符频率映射,算法能够在遍历过程中判断当前窗口是否包含了目标字符串的所有字符,并利用快慢指针技巧优化窗口调整过程。此方法适用于多种字符串匹配问题,如“最小大小子数组”、“最长无重复字符子串”等。文章详细解释了算法的时间复杂度、空间复杂度,并提供了Java代码实现,帮助读者理解和实现这一高效算法。

原题链接在这里: https://leetcode.com/problems/minimum-window-substring/

题目: 

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".

Note:
If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

题解:

把t的char和对应frequency放到map中. count最开始是t.length()

[walker, runner]窗口. s在runner的char若在map中,对应frequency--. count--

当count == 0时, 窗口罩住所有t的char.

移动walker, 直到下一个s在walker的char, 若在map中, 对应frequency++. count++.

Time Complexity: O(sLen). sLen = s.length().

Space: O(1). 256数组map.

AC Java:

 1 public class Solution {
 2     public String minWindow(String s, String t) {
 3         if(s == null || t == null || s.length() < t.length()){
 4             return "";
 5         }
 6         
 7         int [] map = new int[256];
 8         for(char c : t.toCharArray()){
 9             map[c]++;
10         }
11         
12         int count = t.length();
13         int minLen = Integer.MAX_VALUE;
14         int head = 0;
15         int walker = 0; 
16         int runner = 0;
17         while(runner < s.length()){
18             if(map[s.charAt(runner++)]-- > 0){
19                 count--;
20             }
21             while(count == 0){  //count == 0时就表示罩住所有t的char
22                 if(runner - walker < minLen){
23                     minLen = runner - walker;
24                     head = walker;
25                 }
26                 if(map[s.charAt(walker++)]++ == 0){ //让其罩不住所有t的char
27                     count++;
28                 }
29             }
30         }
31         return minLen == Integer.MAX_VALUE ? "" : s.substring(head, head+minLen);
32     }
33 }

类似Minimum Size Subarray SumLongest Substring Without Repeating CharactersLongest Substring with At Most Two Distinct CharactersSubstring with Concatenation of All Words.

对于快慢指针找substring这类问题,通用这个方法.

 1 int findSubstring(int s){
 2     int [] map = new int[256];
 3     int walker = 0;
 4     int runner = 0;
 5     int count; // check whether the substring is valid
 6     int len; // length of substring
 7 
 8     for(){
 9         /*
10         * initialize map.
11         */
12     }
13 
14     while(runner < s.length()){
15         if(map[s.charAt(runner++)]-- ?){
16             /*
17             * modify count.
18             */
19         }
20         while(/*count condition*/){
21 
22             // update len here if finding minimum
23             
24             if(map[s.charAt(walker++)]++ ?) {
25                 //move walker to make it invalid/valid again
26                 //modify count
27             }
28         }
29 
30         //update len here if finding maximum
31     }
32 
33     return len;
34 }

Note: 找maximum substring时,是在while loop 后面更新,因为需要while loop把substring 变valid. 

找minimum substring时,是在while loop之中找, 因为while loop是要把substring 变invalid.

好比Longest Substring Without Repeating Characters.

 1 public class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         int res = 0;
 4         int [] map = new int[256];
 5         int count = 0;
 6         int walker = 0;
 7         int runner = 0;
 8         
 9         while(runner < s.length()){
10             if(map[s.charAt(runner++)]++ > 0){
11                 count++;
12             }
13             while(count > 0){
14                 if(map[s.charAt(walker++)]-- > 1){
15                     count--;
16                 }
17             }
18             res = Math.max(res, runner-walker);
19         }
20         return res;
21     }
22 }

Longest Substring with At Most Two Distinct Characters

 1 public class Solution {
 2     public int lengthOfLongestSubstringTwoDistinct(String s) {
 3         int res = 0;
 4         int [] map = new int[256];
 5         int walker = 0;
 6         int runner = 0;
 7         int count = 0;
 8         while(runner < s.length()){
 9             if(map[s.charAt(runner++)]++ == 0){
10                 count++;
11             }
12             while(count > 2){
13                 if(map[s.charAt(walker++)]-- == 1){
14                     count--;
15                 }
16             }
17             res = Math.max(res, runner - walker);
18         }
19         return res;
20     }
21 }

都是在while loop后面找maximum的substring. 以为while loop 使 substring valid.

Reference: https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-most-substring-problems

转载于:https://www.cnblogs.com/Dylan-Java-NYC/p/4825045.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值