牛客题目链接
1. 题目考点
- 用一个数组来哈希映射一个字符串(
典型,a[ch]++
) - 用双指针来表示一个区间(
滑动窗口
) - 左右指针
交替
向右移动,且不回溯右指针(O(n)
)
2. 考点解析
- 数组哈希字符串 + 双指针滑动窗口(有三个关键地方)
public String minWindow (String S, String T) {
int[] needs = new int[128];
int[] window = new int[128];
for (int i = 0; i < T.length(); i++)
needs[T.charAt(i)]++;
int left = 0, right = 0;
String res = "";
int cnt = 0, minLen = S.length() + 1;
while (right < S.length()) {
char ch = S.charAt(right);
window[ch]++;
if (needs[ch] > 0 && needs[ch] >= window[ch])
cnt += 1;
while (cnt == T.length()) {
ch = S.charAt(left);
if (needs[ch] > 0 && needs[ch] == window[ch])
cnt -= 1;
if (right - left + 1 < minLen) {
minLen = right - left + 1;
res = S.substring(left, right + 1);
}
window[ch] -= 1;
left += 1;
}
right += 1;
}
return res;
}
- leecode 官方解法一:在 S 中挑选目标字符的过程,
加法逻辑
public String minWindow (String S, String T) {
if (S == null || T == null) return "";
int sLen = S.length();
int tLen = T.length();
if (sLen == 0 || tLen == 0 || sLen < tLen)
return "";
int[] winFreq = new int[128];
int[] tFreq = new int[128];
for (int i = 0; i < tLen; i++)
tFreq[T.charAt(i)]++;
int cnt = 0, minLen = sLen + 1;
int left = 0, right = 0, begin = 0;
while (right < sLen) {
char ch = S.charAt(right);
if (tFreq[ch] == 0) {
right++;
continue;
}
if (winFreq[ch] < tFreq[ch])
cnt++;
winFreq[ch]++;
right++;
while (cnt == tLen) {
if (right - left < minLen) {
minLen = right - left;
begin = left;
}
ch = S.charAt(left);
if (tFreq[ch] == 0) {
left++;
continue;
}
if (tFreq[ch] == winFreq[ch])
cnt--;
winFreq[ch]--;
left++;
}
}
if (minLen == sLen + 1) return "";
return S.substring(begin, begin+minLen);
}
- leetcode 官网解法二:减法逻辑
public String minWindow (String S, String T) {
if (S == null || T == null || S == "" ||
T == "" || S.length() < T.length()) return "";
int sLen = S.length();
int tLen = T.length();
int[] tFreq = new int[128];
for (int i = 0; i < tLen; i++)
tFreq[T.charAt(i)]++;
int cnt = tLen, minLen = sLen + 1;
int left = 0, right = 0, begin = 0;
while (right < sLen) {
char ch = S.charAt(right);
if (tFreq[ch] > 0)
cnt--;
tFreq[ch]--;
right++;
while (cnt == 0) {
if (right - left < minLen) {
minLen = right - left;
begin = left;
}
ch = S.charAt(left);
if (tFreq[ch] == 0)
cnt++;
tFreq[ch]++;
left++;
}
}
if (minLen == sLen + 1) return "";
return S.substring(begin, begin+minLen);
}