字节跳动面试题分享003

279 阅读2分钟

2.3字节面试高频(力扣76. 最小覆盖子串)

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

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。

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

  • 示例 1:

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

思路:此题应该使用滑动窗口方法来解答,下面给出思路:

s = "ADOBECODEBANC", t = "ABC"

此时窗口的左指针left和右指针right都为0,此时这个窗口中不含有t中的所有元素,右指针向右移动,直到右指针到达C[下标为5]的时候,

ADOBEC包含ABC,记录下此时的长度,因为要求的是最小的覆盖子串,所以left应该右移看是否有更小的;left到D不符合条件,

此时right应该右移,直到到达A[下标为10]的时候再次符合条件,记录长度,left右移直到left到达O[下标为6]不符合条件,

right右移到达C[最后一个],left调整到A,right右移,超出边界,退出循环;

代码:

​
class Solution {
    public String minWindow(String s, String t) {
        if(t.length() > s.length()) return "";
        int[] om = new int[256];
        int lent = t.length();
        for (int i = 0; i < lent; i++) {
            om[t.charAt(i)]++;
        }                                       //记录下t中的,每个字符字符的数量
        int[] cm = new int[256];
        int left = 0;
        int right = 0;
        int mLeft = 0;
        int mRight = -1;
        int min = Integer.MAX_VALUE;
       for (; right < s.length(); right++) {
           
            if (om[s.charAt(right)] > 0) {     //如果这个字符t中有,cm也应该加一
                cm[s.charAt(right)]++;
            }
            while (isE(om,cm)) {                 //当cm中包含om时
                int m = right - left;
                if (m < min) {
                    mLeft = left;
                    mRight = right;
                    min = m;
                }
                if (om[s.charAt(left)] > 0) {
                    cm[s.charAt(left)]--;
                }
                left++;                        //left右移
            }
        }
        return s.substring(mLeft,mRight + 1);
    }
    public boolean isE(int[] om, int[] cm) {       //如果数组om中的元素小于等于cm中的说明成立,放回true
        for (int i = 0; i < om.length; i++) {
            if (om[i] > cm[i]) {
                return false;
            }
        }
        return true;
    }
}