基线条件(base case)和递归条件(recursive case)
递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。
分而治之(divide and conquer,D&C)
问题:假设你是农场主,有一小块土地。大小为640m × 1680m。你要将这块地均匀地分成方块,且分出的方块要尽可能大。如何将一块地均匀地分成方块,并确保分出的方块是最大的呢?
使用D&C策略!D&C算法是递归的。使用D&C解决问题的过程包括两个步骤。
- 找出基线条件,这种条件必须尽可能简单。(涉及数组的递归函数时,基线条件通常是数组为空或只包含一个元素。)
- 不断将问题分解(或者说缩小规模),直到符合基线条件。
快速排序
快速排序的工作原理。首先,从数组中选择一个元素,这个元素被称为基准值(pivot)。
接下来,找出比基准值小的元素以及比基准值大的元素。这被称为分区(partitioning)。
最后对这两个子数组进行快速排序,再合并结果,就能得到一个有序数组!
快速排序代码:
def quicksort(array): if len(array) < 2: return array else: pivot = array[0] less =[] ''' for i in array[1:]: if i <= pivot: less.append(i) #列表存入元素用append return less ''' #这里用了python的列表解析,后面小贴士会介绍 less = [i for i in array[1:] if i<=pivot] greater = [i for i in array[1:] if i>pivot] return quicksort(less) + [pivot] + quicksort(greater)print(quicksort([10,5,2,3]))print(quicksort([10,5,2,3,11,15,12]))
小结
- D&C将问题逐步分解。使用D&C处理列表时,基线条件很可能是空数组或只包含一个元素的数组。
- 实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。
- 大O表示法中的常量有时候事关重大,这就是快速排序比合并排序快的原因所在。
- 比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n)的速度比O(n)快得多
小贴士
列表解析(List Comprehensions)根据已有列表,高效创建新列表的方式。列表解析是Python迭代机制的一种应用,它常用于实现创建新的列表,因此用在[ ]中。
语法:
- [expression for iter_val in iterable]
- [expression for iter_val in iterable if cond_expr]
例子:1.x = [i for i in list],将一个 list 映射为另一个 list,每个元素设为变量i
2.列出1~10中大于等于4的数字的平方
普通方法:
L = []
or i in range(1,11): if i >= 4: L.append(i**2)print(L)输出:[16, 25, 36, 49, 64, 81, 100]
列表解析:
L = [ i**2 for i in range(1,11) if i >= 4 ]
print(L)输出:[16, 25, 36, 49, 64, 81, 100]