算法64-荷兰国旗问题
題目:
給定一個數組,如[1,2,3,2,3,2,1,2,3,2,1],給出一個int=2,這個值必須存在數組中,要求將數組中的元素按小于int的值在左邊,等于int的值在中間,大于的在右邊
問題來源:
分析:
在說 “荷蘭國旗” 問題之前,首先來看一個引例。
給定一個數組arr,和一個數num,請把小于等于num的數放在數組的左邊,大于num的數放在數組的右邊。要求額外空間復雜度O(1),時間復雜度 O(N)
分析: 設定一個小于等于區,從0開始比較,如果當前數字小于等于num ,讓其與小于等于區的下一個值做交換,再將小于等于區擴大一位,直到將所有的數字都與num進行過比較。重新排好的數組就是所求的數組。如下給出示意過程:
最終就可以得到一個在num左邊所有的數都小于等于num右邊都大于num。
這個過程實際上可以看成是小于等于區域在推著大于等于區域向右走,而當遇到小于等于num的數時,進行的操作是,與大于區域的第一個數字做交換,這聽起來就有些像堆排序的heapify過程。
荷蘭國旗問題(直觀的“分三塊”的問題)
—— 有了上面這些問題的基礎,荷蘭國旗問題就會好想一些。
給定一個數組arr,和一個數num,請把小于num的數放在數組的左邊,等于num的數放在數組的中間,大于num的數放在數組的右邊。要求額外空間復雜度O(1),時間復雜度O(N)
分析: 上一個題目要求將數組分成兩塊,而這個是將數組分成三塊。上一個問題是在左邊設置了一個大于等于區,這個問題可以在左邊設置一個小于區,在右邊設置一個大于區,不斷向中間逼近,最終中間就是相等的數字。操作過程也和上一個問題是完全一樣的。如下過程所示:
有了上面的分析,代碼就很容易理解
代碼:
package mainimport ("fmt"// "math"// "sort"// "time" )func partition(list []int,num int) []int{more:=len(list)less:=-1index:=0for index < more{// fmt.Println("here")if list[index]<num{fmt.Printf("exchange idex %v less %v ",index+1,less+1)swap(list,index,less+1)less++index++//小于去必然小于等于index,將一個小于num的的數放進小于區,不會引起小于區的混亂,//小于去已經是檢查過的區域,必然符合規則,不用重新檢測index位置}else if list[index]>num{fmt.Printf("exchange idx %v more %v ",index,more-1)swap(list,index,more-1)more--//大于區的數未知,放到index位置的話可能引起混亂,所以index不推進,從當前index繼續檢測}else{//等于什么都不做,,所以不會引起任何混亂,直接推進index檢查下一位index++}fmt.Println(index)fmt.Println(list)}fmt.Println(less+1,more-1)result:=[]int{less+1,more-1}return result }func swap(list []int,m,n int){tmp:=list[m]list[m]=list[n]list[n]=tmp } func main(){// list:=[]int{15, 11, 53, 2, 14, 4, 25, 27, 45, 0,30,99,2}list:=[]int{1,2,3,1,2,3,2,1,2,3,2,1,2,2}partition(list,2)}}總結:
1 此方法類似快排的思想,但又有所不同
2 重點在于小于 等于 大于 三種條件的處理完全不同
- 小于-因為小于區是已經排好的,并且當前index指向的值已經知道是小于的,而且index的范圍,相當于小于等于區,交換實質是將小于等于區的數與小于等于區的數交換,交換后還是小于等于區,并不會引起混亂,所以直接index++推進
- 等于-index的指針就是等于區的邊界,所以無需交換,推進index
- 大于-因為大于區的數是未知的,將當前index的數與大于區的數交換,交換過來的數有可能是大于或是小于的,因此index不能推進,要進入下一次循環重新檢測index的值
less小于區,index實際相當于小于等于區
完全理解了上面的邏輯,coding才能進行下去,在此詳細記錄
參考
總結
以上是生活随笔為你收集整理的算法64-荷兰国旗问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无线局域网和蜂窝移动网络_苹果调整 iP
- 下一篇: iis6xp_xp安装iis6步骤方法