leetcode 76. Minimum Window Substring 双指针 + Map + 移动窗口

来源:互联网 发布:新闻 app 源码 编辑:程序博客网 时间:2024/05/29 18:56

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = “ADOBECODEBANC”
T = “ABC”
Minimum window is “BANC”.

Note:
If there is no such window in S that covers all characters in T, return the empty string “”.

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

本题题意很简单,不多说了。最直接的解决方法就是暴力穷举,但是肯定会超时。所以要想一下其他的方法。

这个我是参考网上的一个双指针的解法。具体的做法是这样的:使用map对target字符串做计数处理,这样便于判断当前窗口是否满足包含target的所有元素(还要辅助一个计数器count),这个设计很棒,很值得学习。

使用一个start和end指针遍历字符串,每当发现,当前的窗口包含target的所有元素,那么就开始移动start指针,以缩减窗口,找到最优解。如何判断当前窗口包含target所有的元素,这个就是依靠count计数器。详情看代码吧。

这道题很棒,很值得学习,特别是使用map来做计数器。

建议和leetcode 632. Smallest Range 典型的移动窗口做法 一起学习

代码如下:

import java.util.HashMap;import java.util.Map;public class Solution{    /*     * 双指针思想,尾指针不断往后扫,当扫到有一个窗口包含了所有T的字符,然后再收缩头指针start,     * 直到不能再收缩为止。     * 最后记录所有可能的情况中窗口最小的     *      *      * 最笨的方法肯定要超时,这个肯定要使用到map数据结构    */    public String minWindow(String window, String target)     {        if(window==null || window.length()<=0 || target==null        || target.length()<=0 || window.length()<target.length())            return "";        Map<Character, Integer> needFind=new HashMap<>();        Map<Character, Integer> hasFind=new HashMap<>();        for(int i=0;i<target.length();i++)            needFind.put(target.charAt(i), needFind.getOrDefault(target.charAt(i), 0)+1);        int start=0,end=0,minLen=window.length()+1,count=0;        String res="";        for(;end<window.length();end++)        {            char one=window.charAt(end);            //包含元素,然后去处理            if(needFind.containsKey(one))            {                //修改map                hasFind.put(one, hasFind.getOrDefault(one, 0)+1);                //只有在满足target的情况下才做count++,                //这里的count就是来判断window的截取是否包含target的元素                if(hasFind.get(one) <= needFind.get(one))                    count++;                //只有在找齐所有的元素之后才去做收缩窗口的操作                if(count==target.length())                {                    while(start<end)                    {                        //只要不是当前所包含的start++                        //假如包含,只有计数器大于所需器的的才去做start++,否者直接break                        //因为在做start++就不满足要求了                        char beg=window.charAt(start);                        if(hasFind.containsKey(beg))                        {                            if(hasFind.get(beg)>needFind.get(beg))                            {                                hasFind.put(beg, hasFind.get(beg)-1);                                start++;                            }                            else                                 break;                        }else                             start++;                    }                    //收缩窗口之后的判断                    if(end-start+1 < minLen)                    {                        minLen=end-start+1;                        res=window.substring(start, end+1);                    }                   }            }        }        return res;    }}

下面是C++的做法,就是一个使用双指针和移动窗口来做的,很棒的做法

代码如下:

#include <iostream>#include <string>#include <map>using namespace std;class Solution {public:    string minWindow(string window, string target)     {        if (window.size() <= 0 || target.size() <= 0 || target.size() > window.size())            return "";        map<char, int> needFind,hasFind;        for (int i = 0; i < target.size(); i++)        {            if (needFind.find(target[i]) == needFind.end())                needFind[target[i]] = 1;            else                needFind[target[i]] = needFind[target[i]] + 1;        }        string res = "";        int minLen = window.size() + 1;        int beg = 0  ,count = 0;        for (int end = 0; end < window.size(); end++)        {            char key = window[end];            if (needFind.find(key) != needFind.end())            {                if (hasFind.find(key) == hasFind.end())                    hasFind[key] = 1;                else                    hasFind[key] = hasFind[key] + 1;                if (hasFind[key] <= needFind[key])                    count++;                if (count >= target.length())                {                    while (beg < end)                    {                        char one = window[beg];                        if (hasFind.find(one) != hasFind.end())                        {                            if (hasFind[one] > needFind[one])                            {                                hasFind[one] = hasFind[one] - 1;                                beg++;                            }                            else                                break;                        }                        else                            beg++;                    }                    if (end - beg + 1 < minLen)                    {                        minLen = end - beg + 1;                        res = window.substr(beg,minLen);                    }                }            }        }        return res;    }};
原创粉丝点击