LeetCode 76. 最小覆盖子串
https://leetcode-cn.com/problems/minimum-window-substring/
很典型的滑动窗口题,但是有隐藏了很多的杀机。先上代码吧。
class Solution { public String minWindow(String s, String t) { if(s.length() < t.length() || s.length() == 0 || t.length() == 0){ return ""; } HashMap<Character,Integer> map = new HashMap<>(t.length()); int fast = 0; int slow = 0; int i = 0; String res = ""; int length = Integer.MAX_VALUE; int count = 0; for(; i < t.length(); i++){ map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0) +1); } while(fast < s.length()){ if(map.containsKey(s.charAt(fast))){ map.put(s.charAt(fast), map.get(s.charAt(fast)) -1); if(map.get(s.charAt(fast)).equals(0)){ count++; } while (count == map.keySet().size()){ if((fast - slow + 1) < length){ length = fast - slow + 1; } if(map.containsKey(s.charAt(slow))){ map.put(s.charAt(slow), map.get(s.charAt(slow)) + 1); if(map.get(s.charAt(slow)).intValue() > 0){ count--; } } slow++; } if(length != Integer.MAX_VALUE && length != res.length()){ res = s.substring(fast - length + 1, fast+1); } } fast++; } return res; } }
其实很好理解,先map统计完字符串t中每个字符出现的个数,然后主循环中,如果出现某个字符的个数变成 0,那么它就会满足原来的字符串的其中一个字符条件,所以count++。
如果满足了字符串t中所有的不同字符的情况下,就开始从左手边缩窄滑动窗口,假如遇到其中一个缩窄后个数变成大于0的情况,说明已经出现了不匹配的情况 ,结束循环。
在做完上面这个循环后,再去把我们得到的最小字符串给截取出来,然后快指针++。
这个题坑在哪里呢,leetcode最后两个测试用例规模爆炸,map中存的是对象Integer而不是int,每次比较的时候都会新建一个对象导致最后两个测试用例TLE,这里需要把拆箱利用Java的缓存才能勉强过了。
其实最开始我都没有利用count这个变量。。直接每次循环都检查整个map的所有value是否大于0,如果是就直接不做循环,这样的恶果是导致直接在倒数第二个测试用例中TLE,拆箱再比较还是T了。