https://leetcode.cn/problems/minimum-window-substring/
一、个人版本
public class Solution1 {
public String minWindow(String s, String t) {
Balance balance = new Balance(s, t);
Integer[] idxList = balance.idxList;
if (idxList.length == 0 || idxList.length < t.length()) {
return "";
}
if (t.length() == 1) {
return t;
}
int rightSmallIdx = 0;
int rightIdx = idxList[0];
int leftSmallIdx = 0;
int leftIdx = idxList[0];
int minLeftIdx = leftIdx;
int minRightIdx = s.length();
do {
if (balance.ok()) {
// 左指针右移
Character c = s.charAt(leftIdx);
leftIdx = idxList[++leftSmallIdx];
if (balance.removeAndOk(c) && rightIdx - leftIdx < minRightIdx - minLeftIdx) {
minLeftIdx = leftIdx;
minRightIdx = rightIdx;
}
} else {
if (rightSmallIdx >= idxList.length) {
break;
}
// 右指针右移
rightIdx = idxList[rightSmallIdx++];
if (balance.addAndOk(s.charAt(rightIdx)) && rightIdx - leftIdx < minRightIdx - minLeftIdx) {
minLeftIdx = leftIdx;
minRightIdx = rightIdx;
}
}
} while (true);
if (minRightIdx == s.length()) {
return "";
}
return s.substring(minLeftIdx, minRightIdx + 1);
}
public static class Balance {
private int[] decrMap;
private Integer needSize;
private Integer[] idxList;
public Balance(String s, String t) {
// 构建counter
int[] counter = new int[128];
for (int i = 0; i < t.length(); i++) {
counter[t.charAt(i)]++;
}
this.decrMap = counter;
this.needSize = (int) Arrays.stream(counter).filter(e -> e > 0).count();
this.idxList = IntStream.range(0, s.length()).boxed()
.filter(i -> counter[s.charAt(i)] > 0).toArray(Integer[]::new);
}
public boolean ok() {
return needSize <= 0;
}
private boolean addAndOk(Character c) {
if (--decrMap[c] == 0) {
--needSize;
}
return needSize <= 0;
}
public boolean removeAndOk(Character c) {
if (++decrMap[c] == 1) {
++needSize;
}
return needSize <= 0;
}
}
}
二、最优版本
public class Solution2 {
public String minWindow(String s, String t) {
int[] cnt = new int[128];
for (int i = 0; i < t.length(); i++) {
cnt[t.charAt(i)]++;
}
int left = 0, right = 0, ansLeft = 0, ansRight = 0, ans = Integer.MAX_VALUE, moreT = t.length();
while (right < s.length()) {
// 右指针右移,无论是否命中,cnt[]--
if (cnt[s.charAt(right++)]-- > 0) {
moreT--;
}
// 满足时
while (moreT == 0) {
// 更新
if (right - left < ans) {
ans = right - left;
ansLeft = left;
ansRight = right;
}
// 左指针右移, cnt[]++,绝杀,通过右指针的先行盈亏判断左指针是否需要计入
if (cnt[s.charAt(left++)]++ == 0) {
moreT++;
}
}
}
return ans == Integer.MAX_VALUE ? "" : s.substring(ansLeft, ansRight);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。