最小覆盖子串-java

2 篇文章 0 订阅
2 篇文章 0 订阅

最小覆盖子串-java

题目描述 :
  • 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

    注意:

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

在这里插入图片描述

**解题思想: **
  • 滑动窗口算法是一种用于解决子字符串问题的经典方法。**其核心思想是通过维护一个窗口,根据特定条件移动窗口的左右边界来寻找满足要求的子串。**对于这个问题,我们要在字符串 s 中找到一个最小的子串,使得该子串包含字符串 t 中的所有字符。
  • 该算法的时间复杂度为O(m+n),其中m是字符串s的长度,n是字符串t的长度。这是因为在移动左右边界的过程中,每个字符最多被访问两次,而不会存在重复遍历的情况。
解题思路如下 :
  • 初始化两个频率数组**winFreqtFreq**,用于记录窗口内字符的频率和字符串t中字符的频率。
  • 遍历字符串t,更新**tFreq**数组,记录字符串t中每个字符出现的次数。
  • 初始化窗口的左右边界**leftright,以及记录窗口起始位置begin和最小长度minLen。初始时,将leftright都置为0**,begin置为0minLen置为s.length()+1
  • 开始移动右边界**right,扩大窗口,直到窗口包含了字符串t中的所有字符。每次移动右边界时,更新winFreq数组,并检查是否满足包含字符串t中所有字符的条件。如果满足条件,则开始移动左边界left**,缩小窗口,直到窗口不再满足条件为止。
  • 在移动左右边界的过程中,不断更新最小长度**minLen和起始位置begin**。
  • 最终返回起始位置**begin和最小长度minLen**所对应的子串。
代码实现如下:
class Solution {
public String minWindow(String s, String t){
    if(s.isEmpty() || t.isEmpty() || s.length() < t.length())
        return "";
    int[] winFreq = new int[128];
    int[] tFreq = new int[128];
    for(char c : t.toCharArray())
        tFreq[c]++;

    int minLen = s.length() + 1;
    int begin = 0;
    int left = 0;
    int right = 0;
    int distance = 0;

    while(right < s.length()){
        if(tFreq[s.charAt(right)] == 0){
            right++;
            continue;
        }
        if(winFreq[s.charAt(right)] < tFreq[s.charAt(right)])
            distance++;

        winFreq[s.charAt(right)]++;
        right++;
        while(distance == t.length()){
            if(tFreq[s.charAt(left)] == 0){
                left++;
                continue;
            }
            if(right - left < minLen){
                minLen = right - left;
                begin = left;
            }
            if(winFreq[s.charAt(left)] == tFreq[s.charAt(left)])
                distance--;

            winFreq[s.charAt(left)]--;
            left++;

        }
    }

    if(minLen == s.length() + 1)
        return "";

    return s.substring(begin, begin + minLen);
	}
}

image-20240331011703253

(begin, begin + minLen);
}
}


[外链图片转存中...(img-SJ9FqZJn-1711909639149)]



  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值