题解 | #寻找完成任务所需最短时间#
寻找完成任务所需最短时间
https://www.nowcoder.com/practice/107342346ad44329a35c7e5b890e7d40?tpId=354&tqId=10588489&ru=/exam/oj&qru=/ta/interview-202-top/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D354
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @param t string字符串
* @return string字符串
*/
public String minWindow (String s, String t) {
// write code here
// 创建字符计数映射,记录 t 中每个字符出现的次数
Map<Character, Integer> charCount = new HashMap<>();
for (char c : t.toCharArray()) {
charCount.put(c, charCount.getOrDefault(c, 0) + 1);
}
int left = 0; // 窗口左边界
int minLen = Integer.MAX_VALUE; // 最小子串长度
int minStart = 0; // 最小子串起始位置
int requiredChars = t.length(); // 需要覆盖的字符数
for (int right = 0; right < s.length(); right++) {
char c = s.charAt(right);
if (charCount.containsKey(c)) {
if (charCount.get(c) > 0) {
requiredChars--;
}
charCount.put(c, charCount.get(c) - 1);
}
// 如果已经覆盖了 t 中所有字符
while (requiredChars == 0) {
// 更新最小子串信息
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minStart = left;
}
// 移动窗口左边界,尝试缩小子串
char leftChar = s.charAt(left);
if (charCount.containsKey(leftChar)) {
charCount.put(leftChar, charCount.get(leftChar) + 1);
if (charCount.get(leftChar) > 0) {
requiredChars++;
}
}
left++;
}
}
if (minLen == Integer.MAX_VALUE) {
return "";
}
return s.substring(minStart, minStart + minLen);
}
}
知识点:
- 滑动窗口:通过维护一个窗口来滑动遍历字符串,从而找到符合条件的子串。
- 哈希映射(HashMap):用于存储字符串 t 中每个字符出现的次数,以及窗口中字符出现的次数。
- 双指针:使用左右指针来构建和移动滑动窗口。
解题思路:
使用滑动窗口的技巧来解决问题。我们维护两个指针 left 和 right 来表示窗口的左右边界。我们还使用了一个哈希映射来存储字符串 t 中每个字符出现的次数,以及窗口中字符出现的次数。
我们首先将右指针向右移动,不断更新窗口内字符的出现次数。当窗口内包含了所有 t 中的字符后,我们开始尝试缩小窗口,即移动左指针。通过不断缩小窗口,我们找到一个覆盖 t 中所有字符的最短子串。
查看20道真题和解析