递归算法(二)-分治法
分治法
分治算法的基本思想是將一個規模為N的問題分解為K個規模較小的子問題,這些子問題相互獨立且與原問題性質相同。求出子問題的解,就可得到原問題的解。即一種分目標完成程序算法,簡單問題可用二分法完成。
分治法解題的一般步驟:
實現方法:分治法一般是通過遞歸調用實現的。例如排序算法(快速排序,歸并排序),傅里葉變換(快速傅里葉變換)等。
分治法使用場景
第一條特征是絕大多數問題可以滿足的,問題的復雜性一般是隨著問題規模的增加而增加;第二條特征是應用分治法的前提。它是大多數問題可以滿足的,此特征反映了遞歸思想的應用。第三條特征是關鍵,能否利用分治法完全取決于問題是否具有第三條特征,如果具備了第一條和第二條,而不具備第三條特征,則可以考慮使用貪心法或者動態規劃法。第四條關系到分治法的效率,如果各個子問題是不獨立的則分治法要做尋多不必要的工作,重復的解決公共的子問題,此時雖然可用分治法,但一般使用動態規劃法較好。
歸并排序
歸并排序是采用分治法的一個非常典型的應用。歸并排序的思想就是先遞歸分解數組,再合并數組。
將數組分解最小之后,然后合并兩個有序數組,基本思路是比較兩個數組的最前面的數,誰小就先取誰,取了后相應的指針就往后移一位。然后再比較,直至一個數組為空,最后把另一個數組的剩余部分復制過來即可。
運行結果:
[17, 20, 26, 31, 44, 54, 55, 77, 93]
快速排序
快速排序(英語:Quicksort),又稱劃分交換排序(partition-exchange sort),通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
步驟為:
遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,但是這個算法總會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最后的位置去。
# 快速排序 # 思路:尋抓元素的正確位置,左邊的元素都小于該元素,右邊的都大于該元素 # 移動游標low,high不動則交換直到相遇(可同時交換,也可異步交換) def quick_sort(alist,first,end):# 終止條件if first >= end:returnn = len(alist)mid_value = alist[first]low = firsthigh = endwhile low <high:# 注意處理特殊情況,遇到相等的元素放在一邊處理while low < high and alist[high] >= mid_value:high -= 1alist[low] =alist[high]# low += 1while low < high and alist[low] < mid_value:low += 1alist[high] = alist[low]# high -= 1# 代碼執行到此,alist[0]找到正確位置,解析來把劃分出來的兩段新列表遞歸執行alist[low] = mid_value# 遞歸部分# 對基準元素左邊的子序列進行快速排序quick_sort(alist,first,low-1)# 對基準元素右邊的子序列進行快速排序quick_sort(alist,low+1,end)alist = [54,26,93,17,77,31,44,55,20] quick_sort(alist,0,len(alist)-1) print(alist)運行結果:[17, 20, 26, 31, 44, 54, 55, 77, 93]
多數元素
給定一個大小為 n 的數組,找到其中的多數元素。多數元素是指在數組中出現次數 大于 ? n/2 ? 的元素。
你可以假設數組是非空的,并且給定的數組總是存在多數元素。
class Solution:def majorityElement(self, nums: List[int]) -> int:# 該題分治法不是最優解,但是很好的練習return self.getmajrity(nums,0,len(nums)-1)def getmajrity(self,nums,left,right):# 終止條件if left == right:return nums[left]mid = left + (right - left) // 2leftmajrity = self.getmajrity(nums,left,mid)rightmajrity = self.getmajrity(nums,mid+1,right)#--------------- 此處為分界線上部分為分,下部分為并----------------------# 當左邊的多數元素 與 右邊的多數元素相等時:返回其中任一值,如左邊if leftmajrity == rightmajrity: # 算是一個小優化(可以不要)return leftmajrity# # 如果不相等,需要分別計算左右兩邊,然后比較leftcount,rightcount = 0,0for i in nums[left:right+1]: ## 這里需要+1 否則nums[right]取不到if i == leftmajrity:leftcount += 1elif i == rightmajrity:rightcount += 1if leftcount >= rightcount:return leftmajrityelse:return rightmajrity最大子序列和
給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
參考資料
leetcode 官網
https://zhuanlan.zhihu.com/p/72734354
總結
以上是生活随笔為你收集整理的递归算法(二)-分治法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 薄荷茶的功效与作用、禁忌和食用方法
- 下一篇: 珍珠母粉的功效与作用、禁忌和食用方法