代码随想录——最小覆盖字串(Leetcode76)二刷新思路更简单版本

题目链接
在这里插入图片描述

二刷(滑动窗口)

class Solution {
    public String minWindow(String s, String t) {
        if (s.length() < t.length()) {
            return "";
        }
        HashMap<Character, Integer> maps = new HashMap<>();
        HashMap<Character, Integer> mapt = new HashMap<>();
        
        // 初始化mapt,存储t中每个字符的个数
        for (char c : t.toCharArray()) {
            mapt.put(c, mapt.getOrDefault(c, 0) + 1);
        }
        
        int left = 0;
        int right = 0;
        // 用于跟踪窗口中字符形成t的进度
        int formed = 0; 
        int minLen = Integer.MAX_VALUE;
        int minLeft = 0;
        int minRight = 0;
        
        // 开始滑动窗口
        while (right < s.length()) {
            char c = s.charAt(right);
            maps.put(c, maps.getOrDefault(c, 0) + 1);      
            // 如果当前字符是t中的字符,并且窗口中该字符的数量小于等于t中该字符的数量,则formed加1
            if (mapt.containsKey(c) && maps.get(c) <= mapt.get(c)) {
                formed++;
            }
            
            // 当窗口中的字符形成t时,尝试收缩窗口
            while (formed == t.length()) {
                if (right - left + 1 < minLen) {
                    minLen = right - left + 1;
                    minLeft = left;
                    minRight = right;
                }
                
                // 收缩窗口
                char leftChar = s.charAt(left);
                maps.put(leftChar, maps.get(leftChar) - 1);
                if (mapt.containsKey(leftChar) && maps.get(leftChar) < mapt.get(leftChar)) {
                    formed--;
                }
                left++;
            }
            right++;
        }
        
        // 返回最小窗口
        return minLen == Integer.MAX_VALUE ? "" : s.substring(minLeft, minRight + 1);
    }
}

一刷:滑动窗口思想,无从下手… 还得是困难题

class Solution {
	// 创建两个HashMap来存储目标和窗口中字符的频率
    Map<Character, Integer> ori = new HashMap<Character, Integer>();
    Map<Character, Integer> cnt = new HashMap<Character, Integer>();

    public String minWindow(String s, String t) {
        // 字符串计算长度使用length()方法
        // 获取字符串t长度
        int tLen = t.length();
        for (int i = 0; i < tLen; i++) {
        	// 获取字符串t每一个字符
            char c = t.charAt(i);
            // 将t的每一个字符放入ori哈希表中,计算每个字母出现次数
            ori.put(c, ori.getOrDefault(c, 0) + 1);
        }
        // 初始化左右指针和结果变量
        int l = 0, r = -1;
        int len = Integer.MAX_VALUE, ansL = -1, ansR = -1;
        int sLen = s.length();
         // 当右指针没有到达字符串s的末尾时,执行循环
        while (r < sLen) {
        	// 移动右指针
            ++r;
            // 如果右指针指向的字符在t中,更新计数
            if (r < sLen && ori.containsKey(s.charAt(r))) {
                cnt.put(s.charAt(r), cnt.getOrDefault(s.charAt(r), 0) + 1);
            }
             // 当窗口包含所有t中的字符时,尝试移动左指针缩小窗口
            while (check() && l <= r) {
            	 // 如果当前窗口的长度小于之前的最小长度,更新结果
                if (r - l + 1 < len) {
                    len = r - l + 1;
                    ansL = l;
                    ansR = l + len;
                }
                // 移动左指针前,更新计数
                if (ori.containsKey(s.charAt(l))) {
                    cnt.put(s.charAt(l), cnt.getOrDefault(s.charAt(l), 0) - 1);
                }
                // 移动左指针
                ++l;
            }
        }
        // 根据结果变量返回最小覆盖子串或空字符串
        return ansL == -1 ? "" : s.substring(ansL, ansR);
    }

	// 检查当前窗口是否包含所有t中的字符
    public boolean check() {
    	// 遍历t中的每个字符
        Iterator iter = ori.entrySet().iterator(); 
        while (iter.hasNext()) { 
            Map.Entry entry = (Map.Entry) iter.next(); 
            Character key = (Character) entry.getKey(); 
            Integer val = (Integer) entry.getValue(); 
            // 如果当前窗口中字符的次数小于t中的次数,返回false
            if (cnt.getOrDefault(key, 0) < val) {
                return false;
            }
        } 
        // 如果所有字符的次数都满足条件,返回true
        return true;
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/minimum-window-substring/solutions/257359/zui-xiao-fu-gai-zi-chuan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这段代码的核心思想是使用滑动窗口在字符串s中寻找包含t中所有字符的最小子串。ori用于存储t中每个字符的出现次数,cnt用于存储当前窗口中每个字符的出现次数。通过移动左右指针来扩展和缩小窗口,并在每次移动后检查窗口是否满足条件。如果满足条件,尝试更新结果并继续移动左指针缩小窗口。最后返回找到的最小覆盖子串。

length() :length() 方法用于返回字符串的长度。
charAt():charAt() 方法用于返回指定索引处的字符,索引范围为从 0 到 length() - 1。
containsKey():检查 hashMap 中是否存在指定的 key 对应的映射关系,存在返回 true,否则返回 false。
substring():返回字符串的子字符串。
entrySet():返回映射中包含的映射的 Set 视图(Set 视图意思是 HashMap 中所有的键值对都被看作是一个 set 集合)。
Iterator():Java迭代器,用于遍历集合(如列表、集合和映射等)的接口。
迭代器接口定义了几个方法,最常用的是以下三个:

  • next() - 返回迭代器的下一个元素,并将迭代器的指针移到下一个位置
  • hasNext() - 用于判断集合中是否还有下一个元素可以访问
  • remove() - 从集合中删除迭代器最后访问的元素(可选操作)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值