分而治之(divide and conquer,D&C)
D&C解决问题的过程:
- 找出基线条件,这种条件必须尽可能简单。
- 不断将问题分解(或者说缩小规模),直到符合基线条件。
例子:
将这块地均匀地分成方块,且分出的方块要尽可能大
解决思路如下:
找出最大的,然后剩余的采用同样思路,直到满足基线条件。
快速排序
思路:
- 选择一个元素作为基准值
- 将小于和大于基准值的元素区分,分到两个子数组,此时两个子数组也无序。
- 如果子数组有序, 那么排序后数组为l_arr+ cur_item + r_arr。
- 堆子数组排序,重复上述步骤,
- 基线条件:数组为0或1个元素,一定是有序。
python实现:
def q_sort(arr):
if len(arr) <= 1:
return arr
base_item, l_arr, r_arr = arr[0], [], []
for item in arr[1:]:
if item > base_item:
r_arr.append(item)
else:
l_arr.append(item)
return q_sort(l_arr) + [base_item]+ q_sort(r_arr)
归并排序
思路:
- 二分为两个子数组
- 对子数组递归调用排序
- 对(有序的)子数组 合并时整体排序
- 基线条件:与快排一致
def merge_sort(arr):
if len(arr) <= 1:
return arr
center = len(arr)//2
l_arr, r_arr = merge_sort(arr[:center]), merge_sort(arr[center:])
l_arr_len, r_arr_len = len(l_arr), len(r_arr)
i,j,result = 0,0,[]
while i < l_arr_len and j < r_arr_len:
if l_arr[i] > r_arr[j]:
result.append(r_arr[j])
j += 1
else:
result.append(l_arr[i])
i += 1
return result + l_arr[i:] + r_arr[j:]
复杂度
排序算法 | 大O |
---|---|
选择排序 | O(n)2 |
快速排序 | 平均为nlog(n),最糟为n2 |
合并排序 | nlog(n) |