【Minimum Window】cpp

题目:

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 emtpy string "".

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

代码:

class Solution {
public:
    string minWindow(string s, string t) {
            if (s.empty() && t.empty() ) return "";
            if (s.size()<t.size()) return "";
            const int ASCII_MAX = 256;
            // record how much times a char occurs in t
            int t_char_count[ASCII_MAX] = {0};
            for ( int i=0; i<t.size(); ++i ) { t_char_count[(int)t[i]]++; }
            // record how much times a char occurs in s
            int s_char_count[ASCII_MAX] = {0};
            // global min begin and end index for minimum interval
            int begin_min=-1, end_min=s.size();
            // local min begin ( no need to record local min end ,because it is ‘i‘ )
            int begin = 0;
            int match_size = 0;
            for ( int i=0; i<s.size(); ++i )
            {
                // current interval not match && current char in t
                if ( t_char_count[(int)s[i]]>0 )
                {
                    //cout << s[i] << ":" << t_char_count[s[i]] << endl;
                    s_char_count[(int)s[i]]++;
                    // if a char occurs more times in current interval s than in t, can not increase match_size
                    if ( s_char_count[(int)s[i]]<=t_char_count[(int)s[i]] ) match_size++;
                }
                if ( match_size==t.size() )
                {
                    // move begin forward untill not match
                    while ( begin<=i )
                    {
                        // only address chars not in t
                        if ( s_char_count[(int)s[begin]]>0 )
                        {
                            if ( s_char_count[(int)s[begin]]-1<t_char_count[(int)s[begin]] )
                            {
                                //cout << s_char_count[s[begin]] << endl;
                                match_size--;
                                break;
                            }
                            s_char_count[(int)s[begin]]--;
                        }
                        begin++;
                    }
                    s_char_count[(int)s[begin]]--;
                    // update global min begin and end
                    if ( end_min-begin_min > i-begin ) { end_min = i; begin_min = begin; }
                    begin++;
                }
            }
            if( end_min-begin_min>s.size() ) return "";
            return s.substr(begin_min,end_min-begin_min+1);
    }
};

tips:

曾经以为这种题比较简答,实际上不带算法模板套路的题才是最费神的。

这道题一开始的思路是记录t中每个字符最左边到哪最右边到哪,然后再云云;这个想法不太靠谱。

如果是bruce force暴力解法,时间复杂度可以是O(n²)的:

1. 遍历每个位置,以每个位置为中心,往左右走,直到包含所有的元素,取最短的。

2. 取所有interval中最短的。

可以AC的解法思路如下:

1. 维护几个核心变量:

  a)t中每个字符出现了几次(t_char_count)

  b) s中当前区间里面,t中每个字符出现了几次(s_char_count)

  c) s当前区间是否满足包含t(match_size)

2. 这道题思路很有趣:先找满足包含t的区间;一旦找到了这样的区间,再缩小这样的区间。

  缩减区间的方法:后面的指针保持不动,前面的指针往后移动,直到match_size < t.size(),则证明当前区间已经是最小的满足条件的区间了。

3. 动态更新最小区间。

主要参考:

http://www.cnblogs.com/TenosDoIt/p/3461301.html

http://fisherlei.blogspot.sg/2012/12/leetcode-minimum-window-substring.html

时间: 2024-10-08 09:59:51

【Minimum Window】cpp的相关文章

【Sliding Window】单调队列

题目描述 给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,你只能见到窗口的 K 个整数,每次窗体向右移动一位,如下表: 你的任务是找出窗口在各位置时的最大值和最小值. 输入格式 输入的第 1 行是两个整数 n,k,第 2 行为长度为 n 的数组(即有 n 个整数). 输出格式 输出 2 行,第 1 行是每个位置的最小值,第 2 行是每个位置的最大值. 样例数据 1 输入 [复制] 8 3 1 3 -1 -3 5 3 6 7 输出 -1 -3 -3 -3 3 3 3 3 5

【Edit Distance】cpp

题目: Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) You have the following 3 operations permitted on a word: a) Insert a characterb) Delete a characterc) Rep

【Word Break】cpp

题目: Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words. For example, givens = "leetcode",dict = ["leet", "code"]. Return true becau

【Sudoku Solver】cpp

题目: Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by the character '.'. You may assume that there will be only one unique solution. A sudoku puzzle... ...and its solution numbers marked in red. 代码: cla

【Subsets II】cpp

题目: Given a collection of integers that might contain duplicates, nums, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example,If nums = [1,2,2], a sol

【LRU Cache】cpp

题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.

【Rotate List】cpp

题目: Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1->2->3->4->5->NULL and k = 2,return 4->5->1->2->3->NULL. 代码: /** * Definition for singly-linked list. * struct ListNode {

【Text Justification】cpp

题目: Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified. You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pa

【Simplify Path】cpp

题目: Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", => "/home"path = "/a/./b/../../c/", => "/c" click to show corner cases. Corner Cases: Did you consider the case whe