遞歸式問題解決D&C

分而治之思想
使用D&C解決問題的過程包括兩個步驟:
1.找出基線條件,這種條件必須儘可能簡單;
2.不斷將問題分解(縮小問題規模),直到符合基線條件。
舉例:給定一個數字數組,將這些數字相加返回結果。
使用循環方法:

def sum(arr):
	total = 0
	for x in arr:
		total +=x
		return total
		print sum([1,2,3,4])

如何使用遞歸函數方法呢??
第一步:找出基線條件。最簡單的數組什麼樣呢?–數組中不包含元素,或只含有一個元素,求和最容易。
第二步:每次遞歸調用使其離空數組更近一步,,縮小問題規模。
sum([2,4,6])===2 + sum([4,6])
描述:對於一個列表。若列表爲空,就返回0;否則,計算列表中第一個元素與除去第一個元素的其他數字的求和。
Tips:涉及數組的遞歸函數時,基線條件通常是數組爲空或只包含一個元素

#數組元素求和
def sum(arr):
    if(arr == []):
        return 0
    else:
        return arr[0]+sum(arr[1:])
print(sum([1,2,3,4,5,6,7,8,9,10]))

遞歸函數計算列表中包含的元素數

#列表中元素的個數
def count(arr):
    if (arr == []):
        return 0
    else:
        return 1+count(arr[1:])
print(count([1,2,3,4,5,6,7]))

找出列表中最大的數字(這一個開始沒有想到,所謂最大是在一次次地比較中得出的)

#第一個元素與後面元素比較,選出最大的
def maxNum(arr):
    if len(arr)==2:#最簡單時候,只有兩個元素,比較一下選出大的數
        if(arr[0]>arr[1]):
            return  arr[0]
        else:
            return arr[1]
    else:#第一個元素與後面元素的整體進行比較,從而縮小問題的規模
        if(arr[0]>maxNum(arr[1:len(arr)])):
            return arr[0]

        else:
            return maxNum(arr[1:len(arr)])

print(maxNum([1,2,3,4,5,6,8]))

最後讓我們再仔細回想二分查找中包含的遞歸思想以及涉及的條件

def search(list,item):
        low = 0
        high = len(list) - 1
        #最簡單的情況,數組中只包含一個元素,若要查找的值與這個元素相同就找到了
        while(low<=high):
            mid=int((low+high)/2)
            if(list[mid]<item):#捨棄左邊一半,對右半部分進行二分查找,即縮小了問題規模
                low = mid + 1
            elif(list[mid]>item):
                high = mid - 1
            else:
                return mid

        return None
my_list = [1,2,3,4]
print (search(my_list, 1))
print (search(my_list, 2))

二分查找的遞歸條件中,把數組分爲兩半,將其中一半丟棄,並對另一半執行二分查找。
快速排序也使用了D&C
對排序算法來說,最簡單的數組爲空或只包含一個元素,在這時,根本不用排序
排序的原理:
在數組中選擇一個元素作爲基準值,接着找到比基準值小的元素和比其大的元素進行分區。
part1:小於基準值的數字的子數組;
part2:基準值
part3:大於基準值的數字的子數組;
對子數組進行快速排序,再合併結果,可得有序數組
包含三個元素的數組可以進行排序,在此基礎上遞歸地快速排序,經過歸納證明,以此類推,快速排序對任何長度的數組都管用。

#快速排序
def quicksort(arr):
    if len(arr)< 2:#基準條件:空或只含兩個元素的數組是有序的
       return arr
    else:
        pivot = arr[0]#遞歸條件
        left = [x for x in arr[1:] if x <= pivot]#小於基準值構成的子數組
        right = [x for x in arr[1:] if x > pivot]#大於基準值構成的子數組
        return quicksort(left)+[pivot]+quicksort(right)
print(quicksort([10,5,2,3]))

快速排序在以基準值進行劃分時,在調用棧的每層都涉及O(n)個元素
最佳情況(平均情況):O(nlogn)
最糟情況:o(n^2)
只要每次都隨機地選擇一個數組元素作爲基準值,快速排序的平均運行時間就爲O(nlogn).快速排序是最快的排序算法之一,也是D&C典範。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章