76. 最小覆盖子串

电玩女神 2022-10-13 01:55 326阅读 0赞

链接:https://leetcode-cn.com/problems/minimum-window-substring/

标签:哈希表、字符串、滑动窗口

题目

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

  1. 输入:s = "ADOBECODEBANC", t = "ABC"
  2. 输出:"BANC"

示例 2:

  1. 输入:s = "a", t = "a"
  2. 输出:"a"

提示:

  • 1 <= s.length, t.length <= 105
  • s 和 t 由英文字母组成

**进阶:**你能设计一个在 o(n) 时间内解决此问题的算法吗?

分析

如果要在O(n)时间内解决此题,那么循环肯定是不行的,所以此题使用滑动窗口来解决,也是双指针的一种题型。

思路就是:

(1)使用两个指针left、right,初始left = right = 0。[left, right)称为一个窗口。

(2)right不断右移寻找目标字符放入窗口序列中,直到窗口序列全部包含目标字符。

(3)left右移,把字符从窗口序列中移除,直到窗口序列不包含目标子串,此时得到一个最短的目标子串。

(4)重复(2)(3)两步,不断更新最短目标子串,直到right到达字符串末尾。

其实第(2)步相当于找到了一个可行解,第(3)步就是找到一个最优解

综上,我们需要用到的几个变量是:双指针left和right,窗口序列window,目标序列need,记录最短目标子串的长度。其他的按需增加。

编码

  1. class Solution {
  2. public String minWindow(String s, String t) {
  3. // 目标字符数组
  4. Map<Character, Integer> need = new HashMap<>();
  5. // 窗口数组
  6. int[] window = new int[128];
  7. // valid已找到的字符数
  8. int left = 0, right = 0, valid = 0;
  9. // 最小子串的长度
  10. int len = Integer.MAX_VALUE;
  11. // 最小子串的起始下标
  12. int start = 0;
  13. for (int i = 0; i < t.length(); i++) {
  14. need.put(t.charAt(i), need.getOrDefault(t.charAt(i), 0) + 1);
  15. }
  16. // 右指针往右走
  17. while (right < s.length()) {
  18. char c = s.charAt(right);
  19. right++;
  20. // 说明这个字符包含在目标字符串中
  21. if (need.containsKey(c)) {
  22. window[c]++;
  23. // 找到了一个满足条件的字符(数量够了)
  24. if (window[c] == need.get(c)) {
  25. valid++;
  26. }
  27. }
  28. // 所有的目标字符都已经找到,缩小窗口寻找最小子串
  29. while (valid == need.size()) {
  30. // 更新起始下标和最小子串的长度
  31. if (right - left < len) {
  32. len = right - left;
  33. start = left;
  34. }
  35. // 移出窗口的元素
  36. char d = s.charAt(left);
  37. left++;
  38. if (need.containsKey(d)) {
  39. if (need.get(d) == window[d]) {
  40. valid--;
  41. }
  42. window[d]--;
  43. }
  44. }
  45. }
  46. return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
  47. }
  48. }

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,326人围观)

还没有评论,来说两句吧...

相关阅读