LeetCode 76题:最小覆盖子串

LeetCode 76题是“最小覆盖子串”(Minimum Window Substring)。下面是一个Java解题的示例代码,并附上每行的注释。

import java.util.HashMap;
import java.util.Map;

public class Solution {
    public String minWindow(String s, String t) {
        if (s == null || t == null || s.length() < t.length()) {
            return ""; // 如果s或t为空,或者s的长度小于t,则返回空字符串
        }

        // 记录t中每个字符的出现次数
        Map<Character, Integer> map = new HashMap<>();
        for (char c : t.toCharArray()) {
            map.put(c, map.getOrDefault(c, 0) + 1);
        }

        int left = 0, right = 0; // 左右指针初始化
        int count = map.size(); // 需要匹配的不同字符的数量
        int minLen = Integer.MAX_VALUE; // 用于记录最小窗口长度
        int minLeft = 0; // 记录最小窗口的起始位置

        while (right < s.length()) {
            char c = s.charAt(right); // 获取右指针当前字符

            if (map.containsKey(c)) {
                map.put(c, map.get(c) - 1); // 更新字符出现次数
                if (map.get(c) == 0) {
                    count--; // 如果字符c的计数为0,减少待匹配的字符数量
                }
            }
            right++; // 移动右指针

            // 当所有字符匹配时,尝试缩小窗口
            while (count == 0) {
                if (right - left < minLen) { // 更新最小窗口
                    minLen = right - left;
                    minLeft = left;
                }

                char lc = s.charAt(left); // 获取左指针当前字符
                if (map.containsKey(lc)) {
                    map.put(lc, map.get(lc) + 1); // 恢复字符lc的计数
                    if (map.get(lc) > 0) {
                        count++; // 如果字符lc的计数大于0,增加待匹配的字符数量
                    }
                }
                left++; // 移动左指针
            }
        }

        return minLen == Integer.MAX_VALUE ? "" : s.substring(minLeft, minLeft + minLen); // 返回最小覆盖子串
    }

}

解题思路总结:

  1. 问题理解

    • 给定两个字符串 s 和 t,需要在 s 中找到最短的子串,该子串包含 t 中所有字符的排列。
    • 如果 s 中不存在这样的子串,则返回空字符串。
  2. 滑动窗口方法

    • 使用滑动窗口的技巧,这是一种用于处理子串或子数组问题的常用方法。
  3. 步骤概述

    • 初始化

      • 使用一个哈希表 map 来记录字符串 t 中每个字符的出现次数。
      • 定义两个指针 left 和 right 表示当前窗口的左右边界。
      • 使用一个变量 count 来记录还需要匹配的不同字符的数量。
      • 初始化最小窗口的长度 minLen 和起始位置 minLeft
    • 扩展窗口

      • 移动 right 指针以扩大窗口,逐个检查字符是否在 t 中。
      • 如果字符在 t 中,减少其在 map 中的计数。
      • 如果某个字符的计数变为0,表示该字符已经完全匹配,减少 count
    • 缩小窗口

      • 当 count 为0时,表示当前窗口包含了所有 t 中的字符。
      • 尝试移动 left 指针缩小窗口,寻找更小的可行解。
      • 每次缩小窗口时,检查并更新最小窗口的长度和起始位置。
    • 返回结果

      • 如果找到了符合条件的窗口,返回最小窗口的子串;否则,返回空字符串。
  4. 复杂度

    • 时间复杂度为 O(n + m),其中 n 是字符串 s 的长度,m 是字符串 t 的长度。
    • 空间复杂度为 O(m),用于存储哈希表。

通过这种方法,可以有效地找到字符串 s 中包含 t 的最小覆盖子串。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值