1. 程式人生 > >基於雙指標的滑動視窗方法在陣列問題中的應用

基於雙指標的滑動視窗方法在陣列問題中的應用

LeetCode中有道題:取一個字串中不含重複字元的最長子串的長度。原題是:Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

 最直接的想法是暴力法窮舉所有的子串,取其中不包含重複字元的最長的一個。

result=0
for i=1 to n-1
   for j=i+1 to n
     s=substring(i,j)
     if(s.allunique() and s.length>result)
        result=s.length
return result

其中判斷一個字串是否包含不重複的字元,藉助集合的資料結構,至少需要一趟比較。所以,暴力窮舉的時間複雜度將達到

O(n^{3})。當需要處理的字元創較長時,LeetCode平臺將拒絕接受。

考慮對暴力方法進行優化:當substring(i,j)含有重複字元時,那麼substring(i,k) k\in[i+1,n] 一定會包含重複字元,不用再進行判斷即可,此時需要將頭部指標i向後移動一個單位繼續判斷即可;若substring(i,j)不含有重複字元,則將尾部指標j向後移動一個單位繼續判斷。i和j之間則形成了一個滑動視窗。所以基於雙指標i和j形成如下優化演算法:

i=0
j=1
result=0
while(i<n and j<n)
    while(j<n and substring(i,j).contains(string.chatAt(j)))
        j++
    result=result>j-i?result:j-i
    i++
return result

i,j整體移動一遍就能得到結果,演算法的時間複雜度是O(n),最壞的情況是2*n。

我們重新審視一下這個雙指標形成的滑動視窗,避免了重複的比較和判斷,是處理陣列和字串問題的有效優化方法。LeetCode中給出的解決策略中這樣定義滑動視窗:

A sliding window is an abstract concept commonly used in array/string problems. A window is a range of elements in the array/string which usually defined by the start and end indices, i.e. [i, j)[i,j) (left-closed, right-open). A sliding window is a window "slides" its two boundaries to the certain direction. For example, if we slide [i, j)[i,j) to the right by 11 element, then it becomes [i+1, j+1)[i+1,j+1) (left-closed, right-open).

再另一個經典問題快速排序中,我們同樣可以使用滑動視窗的思想來進行一趟partition。

partition(A,p,r)
x=A[r]
i=p-1
for j=p to r-1
    if A[j]<=x
        i++
        exchange A[i] with A[j]
exchange A[i+1] with A[r]
retur i+1