Java 求解最小覆盖子串

Posted 南淮北安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 求解最小覆盖子串相关的知识,希望对你有一定的参考价值。

一、题目

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

注意:

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

二、题解

采用滑动窗口的思想

用i,j表示滑动窗口的左边界和右边界,通过改变i,j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j-i+1,这些长度中的最小值就是要求的结果。

  • 不断增加j使滑动窗口增大,直到窗口包含了T的所有元素
  • 不断增加i使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度减小,直到碰到一个必须包含的元素,这个时候不能再扔了,再扔就不满足条件了,记录此时滑动窗口的长度,并保存最小值
  • 让i再增加一个位置,这个时候滑动窗口肯定不满足条件了,那么继续从步骤一开始执行,寻找新的满足条件的滑动窗口,如此反复,直到j超出了字符串S范围。

需要一个数组维护当前滑动窗口需要的各元素数量

三、代码

class Solution 
    public String minWindow(String s, String t) 
        //ASCII字符的范围最大到127
        int[] chars = new int[128];
        //记录需要的字符个数
        for (char ch : t.toCharArray()) 
            chars[ch]++;
        
        //left滑动窗口左边界
        //start记录最小的窗口起始下标
        //count记录窗口还需要多少字符满足条件
        int left = 0, start = 0, size = Integer.MAX_VALUE, count = t.length();
        //遍历所有字符
        for (int right = 0; right < s.length(); right++) 
            char ch = s.charAt(right);
            if (chars[ch] > 0) 
                count--;
            
            chars[ch]--;
            //窗口包含所有字符
            if (count == 0) 
                //开始收缩窗口
                while (right > left && chars[s.charAt(left)] < 0) 
                    chars[s.charAt(left)]++;
                    left++;
                
                if (size > right - left + 1) 
                    size = right - left + 1;
                    start = left;
                
                //窗口左移
                chars[s.charAt(left)]++;
                left++;
                count++;
            
        
        return size == Integer.MAX_VALUE ? "" : s.substring(start, start + size);
    

四、总结

left 和 right 都会扫描一遍 字符串 S,最多扫描两次,所以时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( k ) O(k) O(k)
k 为 S 和 T 中字符的集合

以上是关于Java 求解最小覆盖子串的主要内容,如果未能解决你的问题,请参考以下文章

数据机构与算法之深入解析“最小覆盖子串”的求解思路与算法示例

76. 最小覆盖子串

76. 最小覆盖子串

双指针最小覆盖子串(滑动窗口)(medium)

双指针最小覆盖子串(滑动窗口)(medium)

76. 最小覆盖子串 (JAVA)