Leetcode第76题

这篇博客详细介绍了如何利用滑动窗口算法解决LeetCode上的第76题,即找出给定字符串s中涵盖字符串t所有字符的最小子串。文中提到,通过两个HashMap分别存储t和滑动窗口sMap的有效字符及其个数,通过不断移动右指针并调整左指针,找到满足条件的最短子串。同时,提供了具体的Java实现代码,包括关键的compareMap方法,用于比较两个HashMap中的字符个数是否匹配。
摘要由CSDN通过智能技术生成

Leetcode第76题

题目

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

注意

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

思路:

  • 我们可以用滑动窗口来解决这个问题。
  • 由于字符串 t 要统计重复字符,所以可以用HashMap来保存 t 中的字符及个数,用另一个HashMap来动态存储滑动窗口中的有效字符(即t中出现过的字符)及个数,然后比较两个HashMap,找到最短的子字符串。

代码:

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

/*
 * @lc app=leetcode.cn id=76 lang=java
 *
 * [76] 最小覆盖子串
 */

// @lc code=start
class Solution
{
    public String minWindow(String s, String t)
    {
        // 动态的保存滑动窗口中的有效字符(t中包含的字符)及其个数
        Map<Character, Integer> sMap = new HashMap<>();
        // 保存t中的字符及其个数
        Map<Character, Integer> tMap = new HashMap<>();
        // 滑动窗口的左指针
        int left = 0;
        // 记录最优解的左边界
        int ansLeft = 0;
        // 临时保存map中的key
        Character key;
        // 临时保存map中的value
        Integer value;
        // 记录滑动窗口的最小长度,即最短的子序列
        int minLen = Integer.MAX_VALUE;
        // 首先把t字符串中所有字符都取出来,计算每个字符的个数,存放入map中
        for (int i = 0; i < t.length(); i++)
        {
            key = t.charAt(i);
            if (tMap.get(key) != null)
            {
                value = tMap.get(key);
                tMap.put(key, value + 1);
            }
            else
            {
                tMap.put(key, 1);
            }
        }
        // right为滑动窗口的右指针
        for (int right = 0; right < s.length(); right++)
        {
            key = s.charAt(right);
            // 如果右指针指向的字符是t中的某个字符,那么就把这个字符在sMap中加1
            if (tMap.containsKey(key))
            {
                if (sMap.get(key) != null)
                {
                    value = sMap.get(key);
                    sMap.put(key, value + 1);
                }
                else
                {
                    sMap.put(key, 1);
                }
            }
            // 比较滑动窗口sMap中的有效字符及个数是否 >= tMap中的字符个数
            while (compareMap(sMap, tMap))
            {
                // 这里为了减少无效字符的判断次数,直接将左指针指向滑动窗口中的最左边的有效字符
                key = s.charAt(left);
                while (!tMap.containsKey(key))
                {
                    left++;
                    key = s.charAt(left);
                }
                // while循环完,此时left指向的key是一个有效的字符
                // 取一个最短的符合要求的子序列
                if (minLen > right - left + 1)
                {
                    minLen = right - left + 1;
                    ansLeft = left;
                }
                // 将left向左移动,缩小窗口的范围,判断是否仍然符合要求
                value = sMap.get(key);
                sMap.put(key, value - 1);
                left++;
            }
        }
        return minLen != Integer.MAX_VALUE ? s.substring(ansLeft, ansLeft + minLen) : "";
    }

    // compare two map
    // 比较滑动窗口sMap中的有效字符及个数是否 >= tMap中的字符个数
    public boolean compareMap(Map<Character, Integer> sMap, Map<Character, Integer> tMap)
    {
        Character key;
        Integer value;
        for (Map.Entry<Character, Integer> entry : tMap.entrySet())
        {
            key = entry.getKey();
            value = entry.getValue();
            if (sMap.containsKey(key) && sMap.get(key) >= value)
            {

            }
            else
            {
                return false;
            }
        }
        return true;
    }
}

// @lc code=end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值