1. 程式人生 > >字串問題---最小包含子串的長度

字串問題---最小包含子串的長度

【題目】

  給定字串str1和str2,求str1的子串中含有str2所有字元的最小子串長度。

【舉例】

  str1 = “aabcde”, str2 = “ca”。返回3.
  str1 = “12345”, str2 = “344”。返回0.

【基本思路】

  使用一個雜湊表記錄str2中每一個字元出現的次數。需要四個變數:left,right表示str1子串str1[left…right]的兩邊界下標,match表示在子串str1[left…right]中目前一共欠str2多少個字元。minlength記錄整個遍歷過程中出現的最小的子串長度。初始時,left = right = 0,match = len(str2),minlength = 系統的最大值。
  
  遍歷str1,先向右擴張right,當遇到str2中的字元是,將map中相應的值 -1,同時match也 -1;如果遇到的不是str2中的字元,將(str1[right],-1)記錄到map中。當match == 0時,說明str1[left…right]已經包含了str2中的所有字元,但是此時的子串長度還不是該子串的最小長度,例如,例1中開始出現兩個a,但是第二個a到c的距離才是最小距離。所以接下來還有一個向右擴張left的過程。
  
  向右擴張left,如果map[str1[left]] < 0,說明此時如果把這個字元撿起來,str1[left…right]中也不會欠str2字元,所以撿起該字元。如果map[str1[left]] == 0,說明一旦撿起該字元,那麼str1[left…right]必然會欠str2一個字元,所以此時left擴張終止,此時left到right的值便是一個最小子串。
  
  令match+1,map[str1[left]]+1,從left的下一個位置開始,繼續擴張right和left尋找下一個最小的子串。整個過程中使用minlength記錄最小的子串長度。
  
如果str1的長度為N,該做法的時間複雜度為O(N)

下面是使用python3.5實現的程式碼。

#最小包含子串的長度
def minLength(str1, str2):
    if str1 == None or str2 == None or len(str1) < len(str2):
        return 0
    map = [0 for i in range(256)]
    for i in range(len(str2)):
        map[ord(str2[i])] += 1
    left = 0
    right = 0
    match = len(str2)
    minlength = sys.maxsize
    while
right < len(str1): map[ord(str1[right])] -= 1 if map[ord(str1[right])] >= 0: match -= 1 if match == 0: while map[ord(str1[left])] < 0: map[ord(str1[left])] += 1 minlength = min(minlength, right - left + 1) match += 1
map[ord(str1[left])] += 1 left += 1 right += 1 return minlength if minlength != sys.maxsize else 0