题解 | #寻找完成任务所需最短时间#
寻找完成任务所需最短时间
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 中所有字符的最短子串。