zoukankan      html  css  js  c++  java
  • Leetcodee 76. 最小覆盖子串 双指针 哈希

    地址 https://leetcode-cn.com/problems/minimum-window-substring/

    给你一个字符串 s 、一个字符串 t 。
    返回 s 中涵盖 t 所有字符的最小子串。
    如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
    
    注意:
    对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
    如果 s 中存在这样的子串,我们保证它是唯一的答案。
     
    示例 1:
    输入:s = "ADOBECODEBANC", t = "ABC"
    输出:"BANC"
    
    示例 2:
    输入:s = "a", t = "a"
    输出:"a"
    
    示例 3:
    输入: s = "a", t = "aa"
    输出: ""
    解释: t 中两个字符 'a' 均应包含在 s 的子串中,
    因此没有符合条件的子字符串,返回空字符串。
     
    
    提示:
    1 <= s.length, t.length <= 105
    s 和 t 由英文字母组成
     
    
    进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
    

    解答
    之前有谈过滑动窗口双指针的方法。
    可以动态的扩大缩小连续的字符串,那么我们可以使用该方法获取最短长度满足涵盖目标字符串的子字符串。
    如图


    确认使用双指针后,还有一个问题需要解决,如何快速的判断当前双指针的范围内的字符串是否涵盖目标字符串。
    可以使用哈希,快速的记录和查询当前字母是否包含在某段范围内。
    扩大范围的时候 就把扩大包含的字母记录到哈希表中
    缩小范围的时候 就把缩小抛弃的字母移出哈希表,或者说从哈希表中删除
    缩小范围的操作

    if (mm.count(s[l]) != 0) {
      //记录减1
      checkm[s[l]]--;
    }
    //移动左指针 缩小范围
    l++;
    

    扩大范围的操作

    r++;
    if (r < s.size() && mm.count(s[r]) != 0) {
      checkm[s[r]]++;
    }
    

    全部代码如下

    class Solution {
    public:
    	unordered_map<char, int> mm;
    
    	void init(const string& s) {
    		for (auto& e : s) {
    			mm[e]++;
    		}
    	}
    	bool isEqual(unordered_map<char, int>& a, unordered_map<char, int>& b) {
    		if (a.size() != b.size()) return false;
    
    		for (auto& e : b) {
    			if (e.second < a[e.first]) return false;
    		}
    
    		return true;
    	}
    	string minWindow(string s, string t) {
    		init(t);
    		int l = 0; int r = 0;
    		unordered_map<char, int> checkm;
    		if (mm.count(s[r]) != 0) {
    			checkm[s[r]]++;
    		}
    		int ans = 999999; int ansl = -1; int ansr = -1;
    		while (l < s.size() && r < s.size()) {
    			if (isEqual(mm, checkm)) {
    				//缩小范围
    				if (ans > (r - l + 1)) {
    					ans = r - l + 1; ansl = l; ansr = r;
    				}
    				if (l <= r) {
    					if (mm.count(s[l]) != 0) {
    						checkm[s[l]]--;
    					}
    					l++;
    				}
    
    			}
    			else {
    				//扩大范围
    				r++;
    				if (r < s.size() && mm.count(s[r]) != 0) {
    					checkm[s[r]]++;
    				}
    			}
    		}
    		if (ansl == -1)return "";
    		string ansstr = s.substr(ansl, ansr - ansl + 1);
    		return ansstr;
    	}
    };
    

    我的视频题解空间

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    编程范式 epesode7,8 stack存放指针类型and heap,register
    编程范式 episode 6 实现stack 栈功能_ to do
    C 运算符优先级
    编程范式 episode3 and 4,5
    编程范式 epesode2 negative values, float 精度
    C 数据类型 长度
    memcpy code
    排序算法 2 qsort 库函数,泛型函数
    sin, miss the mark, correct our aim and try again
    排序算法 1
  • 原文地址:https://www.cnblogs.com/itdef/p/15678850.html
Copyright © 2011-2022 走看看