字串問題---最小包含子串的長度
【題目】
給定字串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