2014-10-27

過去一週沒有寫letcode。

原因是備戰學生期間的最後一門考試,更主要的原因是自己懶。。。

今天的題目是最小字符串範圍。

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.

Hide Tags Hash Table Two Pointers String
這道題想了一下午,最後還是看了別人的解題思路後自己重新編一遍。

前期的思維障礙主要做O(n)上面。一開始一直只想一遍遍歷直接通過T中每個字符在S中的位置的數字關係來決定。

這個思路下,每個字符在S中的位置關係是一個矩陣。

例如 S=“aabddc”,T="abc".

則位置關係就是

1 2 0 0 0 0
0 0 3 0 0 0
0 0 0 0 0 6
然後沒有想出根據矩陣解決的辦法。思維定勢後就無法再從其他的方法入手了。


看了別人的代碼後,就很明朗了。就是普通的暴力了···


普通暴力中有一個前提,從左到右,依次暴力而不是整個字符串S逐漸縮小。


具體流程是:

1.找出S中第一次出現T中所有字符的字符串範圍[0,indexS],

例如 S=“aabddc”,T="abc".則第一次出現T中所有字符的字符串範圍就是[0,5]

S="abdcaabc",T="abc",則第一次出現T中所有字符的字符串範圍就是[0,3]


2.在上述得到的範圍中[start,end]逐漸移動start,使之向右移。移動的條件是:start移動後,S[start,end]中依然包含着T中所有字符,直到不能再移動位置。

這個時候就得到一個最小範圍。

例如S=“aabddc”,T="abc".則第一次出現T中所有字符的字符串範圍就是[0,5]。

start=0,end=5.start可以移動1的位置上,因爲S[1,5]仍然包含了T中的所有字符。

S="abdcaabc",T="abc",則第一次出現T中所有字符的字符串範圍就是[0,3]。

start=0,end=3.start無法向右移動,因爲移動後,S[1,3]就不含有T中字符‘a’;

3.向右移動end後,繼續進行2操作。直到end移動到最後。然後就得到了最小的窗口距離。


其中,在判斷S和T中是否出現相同的字符串的時候並不是用比較的方法來做,而是用字符有ascII數值,轉換成數組中的具體位置來達到比較的效果。


上代碼

public class Solution {

	public static void main(String[] args) {
		System.out.println((new Solution()).minWindow("aa", "aa"));
	}

	public String minWindow(String S, String T) {
		int[] NeedFind = new int[256];
		int[] HadFind = new int[256];
		for (int indexT = 0; indexT < T.length(); ++indexT)
			NeedFind[T.charAt(indexT)]++;
		int count = 0;// 記錄
		int begin = 0;
		int mindis = S.length()+1;
		int start=0;
		for (int indexS = 0; indexS < S.length(); ++indexS) {
			if (NeedFind[S.charAt(indexS)] > 0) {// 碰到了T中的字符串
				if (HadFind[S.charAt(indexS)] < NeedFind[S.charAt(indexS)])count++;//這裏不能寫成<span style="font-family: Arial, Helvetica, sans-serif;">if (HadFind[S.charAt(indexS)] ==0),因爲T中可能出項相同的字符。</span>
				HadFind[S.charAt(indexS)]++;
				if (count >= T.length()) {//這個範圍已經包含了T中所有字符
					while (NeedFind[S.charAt(begin)]==0||HadFind[S.charAt(begin)] > NeedFind[S.charAt(begin)]) {
						HadFind[S.charAt(begin)]--;
						begin++;
					}
					//System.out.println("begin="+begin);
					if (mindis > indexS - begin + 1)
					{
						start=begin;
						mindis = indexS - begin + 1;
					}
				}
			}
		}
		if(mindis==S.length()+1)return "";//沒有包含任何字符。
		return S.substring(start,start+mindis);
	}
}




發佈了42 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章