前言
保持前缀和、滑动窗口对连续子数组和子字符串的敏感性,才能实现问题的转换,以及举一反三的改进。
一、案例
二、题解
用map记录t每个字符的个数,然后以滑动窗口匹配s,记录的负数表示多出来的,正数表示还缺多少。
每次正数减一,count就加一,加到t的长度就可以比较哈子字符串的大小了;每次begin指针滑动的时候。
map里没有包含begin字符的就不管,否则就看begin字符是处于有无库存的状态,有库存,count不变,无库存,count-1;
package com.xhu.offer.offerII;
import java.util.HashMap;
import java.util.Map;
//含有所有字符的最短字符串
public class MinWindow {
public String minWindow(String s, String t) {
//用map记录t每个字符的个数,然后以滑动窗口匹配s,记录的负数表示多出来的,正数表示还缺多少。
//每次正数减一,count就加一,加到t的长度就可以比较哈子字符串的大小了;每次begin指针滑动的时候。
// map里没有包含begin字符的就不管,否则就看begin字符是处于有无库存的状态,有库存,count不变,无库存,count-1;
int len1 = s.length(), len2 = t.length();
if (len1 < len2) return "";
int[] res = new int[]{len1 + 1, 0};
Map<Character, Integer> cache = new HashMap<>();
for (int i = 0; i < len2; i++) {
Character ch = t.charAt(i);
cache.put(ch, cache.getOrDefault(ch, 0) + 1);
}
int begin = 0, end = 0, count = 0;
for (; end < len1; end++) {
Character ch = s.charAt(end);
if (!cache.containsKey(ch)) continue;
int n = cache.get(ch);
count += n > 0 ? 1 : 0;
cache.put(ch, n - 1);
if (count == len2) {
while (begin <= end) {
if (count != len2) break;
int len = end - begin + 1;
if (len < res[0]) {
res[0] = len;
res[1] = begin;
}
Character c = s.charAt(begin);
if (cache.containsKey(c)) {
int m = cache.get(c);
count -= m == 0 ? 1 : 0;
cache.put(c, m + 1);
}
begin++;
}
}
}
return s.substring(res[1], res[0] == len1 + 1 ? 0 : res[1] + res[0]);
}
}
总结
1)保持逻辑清晰性,能做来就整理好逻辑,一步一步代码实现,逻辑通不了就别发呆,去看题解。
2)保持前缀和、滑动窗口对连续子数组和子字符串的敏感性,才能实现问题的转换,以及举一反三的改进。
参考文献
[1] LeetCode 原题