尺取法其實是一種很簡單的算法,思想原來也用過,但一直不知道。。這兩天恰好做了兩道有關尺取法的題,就來總結一下。
首先,什么是尺取法?尺取法通常是指對數組保存一對下標(起點、重點),然后根據實際情況交替推進兩個端點直到得出答案的方法,因為這種方法像尺取蟲的爬行方式所以得名。其實就是求在一個線性的數組上求關於區間的問題。由於只對區間的兩個端點進行改變,所以中間部分就不需要進行維護更新了,只要維護兩端即可。可以大大降低復雜度。
例題一:poj3061 給定長度為n的整數數列以及整數S,求出總和不小於S的連續子序列的長度的最小值,如果解不存在,輸出0。
解法一:(1)s=t=sum=0初始化
(2)只要sum<S,就不斷將sum增加a(t),並將t增加1
(3)如果(2)中無法滿足sum>=S則終止,否則將ans更新為min(ans,t-s)。
(4)將sum將sum減去a(s),s增加1后回到(2)
這其實就是一個典型的尺取法,我們當得到sum>=S時再減去a(s)它又會小於S就相當於重新確定了起點,同樣的,也就同時確定了終點,並且因為新區間和原來的區間有很大一部分重合,所以直接對sum進行加減就可以了,無需重新計算。
例題二:給出一串珠子,有2n個,其中有黑色和白色珠子各n個,黑色逆時針編號,白色順時針編號,白色黑色隨機排列,要找一段長度為n的區間,要求區間內珠子的編號為1-n(不一定從小到大或從大到小出現,只要1-n都出現即可)。(感謝暢神出題!)數據范圍1000萬。
解法二:由於數據范圍很大,所以必須用O(n)的方法解。我們先把珠子編好號,然后找一個作為起點,向后找n個珠子,記錄下每種編號的珠子各有幾個和一共出現了幾個編號的珠子。然后,我們將頭上的珠子取出,加上第n+1個珠子,重復該過程,直到出現了n個編號的珠子我們就找到了一個合法區間。這也是尺取法的一種,中間n-2個珠子我們是不需要管的,只要取出和加上頭和尾的珠子就行了。這樣只要枚舉n個起點就可以輕松找出這個區間。
總結:總的來說尺取法的思想很好理解,代碼難度不算高,在noip中考很合適,有些題可以方便的解決,個人感覺應該掌握。