1. 程式人生 > >包含K個不同字元的最長子串-滑動視窗法-Python2.7

包含K個不同字元的最長子串-滑動視窗法-Python2.7

  • 題目描述: 給定一個字串和一個正數k,尋找一個包含k個不同字元的最長子串。如果k大於字串中所有不同字元的個數,就返回整個字串。
  • 輸入描述: 正數k 字串s
  • 輸出描述: 字串

  • 樣例輸入: k = 2, s = ‘abcbdbdbbdcdabd’ k = 3, s = ‘abcbdbdbbdcdabd’ k = 5, s = ‘abcbdbdbbdcdabd’

  • 樣例輸出: k = 2 時,輸出 ‘bdbdbbd’ k = 3 時,輸出 ‘bcbdbdbbdcd’ k = 5 時,輸出 ‘abcbdbdbbdcdabd’
  • 思路: 滑動視窗法。 滑動視窗法描述:滑動視窗法用一個視窗去滿足問題的約束條件。一旦違反約束條件,視窗就會變得不穩定,為了消除這種不穩定,重新滿足約束條件,我們需要通過增加或減小視窗的大小。 在這個問題中,遍歷字串,如果視窗中不同字元個數小於k,則將字元加入到視窗中。如果不同字元的個數大於k,則從最左邊的字元開始刪除,直到視窗中不同字元的個數等於k。我們反覆進行這種改變視窗大小的操作,直到遍歷完整個字串。在這個過程中,如果視窗大小改變,我們就更新最大視窗值。 Python2.7實現
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/9/16 14:03
# @Author  : Qiankun Wang
# @File    : LongestSubstringK.py
# Function: Find the longest substring fo given string containing k distinct characters using sliding window
# Reference: http://www.techiedelight.com/find-longest-substring-containing-k-distinct-characters/
def LongestSubstringK(s,k): begin = 0 # 儲存子串的起點 end = 0 #儲存子串的終點 window = set() freq = dict(zip(s,[0]*len(s))) #字元出現的頻率 low = 0 # 視窗的左邊界 # 遍歷字串,將每個字元加入到視窗中,並更新該字元對應的出現頻率。 for high in range(len(s)): # high為視窗的右邊界 window.add(s[high]) freq[s[high]] += 1 # 一旦約束條件不滿足:即視窗中包含的不同字元的個數大於指定的k,則從左側開始縮減視窗的大小。
while len(window) > k: # 如果字元只出現一次,我們把該字元從視窗中去除,同時將其對應的頻率減一。 if freq[s[low]] -1 == 0: window.remove(s[low]) freq[s[low]] -= 1 low += 1 # 縮減視窗的大小 # 更新視窗的大小(如果條件滿足的話) if end - begin < high - low: end = high begin = low # 返回滿足條件的最長子串 return s[begin:end+1] if __name__ == "__main__": s = 'abcbdbdbbdcdabd' k = 2 print LongestSubstringK(s,k)