• [LeetCode] 76. Minimum Window Substring(最小窗口子串)


    Description

    Given two strings s and t, return the minimum window in s which will contain all the characters in t. If there is no such window in s that covers all characters in t, return the empty string "".
    给定两字符串 st,返回 s 的一个最小窗口(子串),该子串包含 t 中所有字符。如果找不到这样的窗口(子串),则返回空串 ""

    Note that If there is such a window, it is guaranteed that there will always be only one unique minimum window in s.
    注意,如果存在这样的窗口(子串),输入保证该窗口(子串)唯一。

    Examples

    Example 1

    Input: s = "ADOBECODEBANC", t = "ABC"
    Output: "BANC"
    

    Example 2

    Input: s = "a", t = "a"
    Output: "a"
    

    Constraints

    • 1 <= s.length, t.length <= 1e5
    • s and t consist of English letters.

    Follow up

    Could you find an algorithm that runs in O(n) time?

    Hints

    1. Use two pointers to create a window of letters in S, which would have all the characters from T.

    2. Since you have to find the minimum window in S which has all the characters from T, you need to expand and contract the window using the two pointers and keep checking the window for all the characters. This approach is also called Sliding Window Approach.

      L ------------------------ R , Suppose this is the window that contains all characters of T
      
              L----------------- R , this is the contracted window. We found a smaller window that still contains all the characters in **T**
      

      When the window is no longer valid, start expanding again using the right pointer.

    Solution

    子串问题优先考虑滑动窗口。首先需要统计 t 中字母出现的次数。然后扩展窗口右边界,寻找能包含 t 中所有字母的窗口,再扩展窗口左边界,去掉“不必要的字母”。代码如下:

    class Solution {
        fun minWindow(s: String, t: String): String {
            if (s.length < t.length) {
                return ""
            }
            val countMap = hashMapOf<Char, Int>()
            t.forEach { countMap[it] = (countMap[it] ?: 0) + 1 }
    
            var left = 0
            // 统计窗口内匹配到了 t 中的多少字母
            var match = 0
            var minLength = Int.MAX_VALUE
            var result = ""
    
            for (right in s.indices) {
                // 为什么直接在原 map 上改?
                // 这是为了方便统计,直接在 map 上改,那么判断“窗口恰好包含 t 中所有字母”的条件是
                // map 里所有 t 包含的字母,对应的频率为 0
                // 对于 t 不包含的字母,其对应的 value 永远小于 0
                countMap[s[right]] = (countMap[s[right]] ?: 0) - 1
                if (countMap.getValue(s[right]) >= 0) {
                    match++
                }
                while (match == t.length) {
                    if (minLength > right - left + 1) {
                        minLength = right - left + 1
                        result = s.substring(left..right)
                    }
                    countMap[s[left]] = (countMap[s[left]] ?: 0) + 1
                    if (countMap.getValue(s[left]) > 0) {
                        // 窗口收缩导致 t 中有一个字母没包括进去
                        match--
                    }
                    left++
                }
            }
            return result
        }
    }
    
  • 相关阅读:
    权限框架之Shiro详解(非原创)
    MySQL数据库基础详解(非原创)
    ssm(Spring、Springmvc、Mybatis)实战之淘淘商城-第十四天(非原创)
    ssm(Spring、Springmvc、Mybatis)实战之淘淘商城-第十三天(非原创)
    nginx配置location与rewrite规则教程
    CentOS7安装MySQL 5.7
    MySQL 5.6 解决InnoDB: Error: Table "mysql"."innodb_table_stats" not found.问题
    公文流转系统(未完成)
    对java异常的总结及java项目中的常用的异常处理情况
    课堂动手动脑验证以及自定义异常类实现对异常处理——java异常类
  • 原文地址:https://www.cnblogs.com/zhongju/p/14182901.html
Copyright © 2020-2023  润新知