理解部分
D&C 策略! D&C算法是递归的。使用D&C解决问题的过程是分为两个步骤:
1 、找到基线条件,这种条件必须尽可能的简单
2、不断的将问题分解(或者说是缩规模), 直到符合基线条件。
D&C并非是解决问题的算法,而是解决问题的一种思路!
看个例子
求 数组数字的和
let nubs = [2,4,6]
let sum = function (arr) {
let total = 0;
arr.map(item => {
total += item
})
return total
}
这种很容易
但是如何使用递归函数来完成这种任务呢
function add(arr) {
if (arr.length == 1) return arr[0]
console.log(arr)
return arr[0] + add(arr.slice(1))
}
快速排序
(1)在数据集之中,选择一个元素作为"基准"(pivot)。
(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
代码实现
var quickSort = function(arr) {
if (arr.length <= 1) {
return arr;
}
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++){
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
};
console.log(quickSort([12,23,433,3,4,2,56,76]))
首先,定义一个quickSort函数,它的参数是一个数组。
然后,检查数组的元素个数,如果小于等于1,就返回。
接着,选择"基准"(pivot),并将其与原数组分离,再定义两个空数组,用来存放一左一右的两个子集。
然后,开始遍历数组,小于"基准"的元素放入左边的子集,大于基准的元素放入右边的子集。
最后,使用递归不断重复这个过程,就可以得到排序后的数组。
使用的时候,直接调用quickSort()就行了。
再谈大O表示法
1. 快速排序的时候取第一个值为基准值 是最糟糕的情况 栈长为O(n)
2. 将中间的元素作为基准值 是最佳的情况 栈长为O(log n)
只要每次的都选择一个数组元素作为基准值,快速排序的平均时间就将为O(n log n)。快速排序是最快的排序算法之一,也是D&C典范。
1、O(n)
2、 O(n)
3、O(1)
4、O(n²)
小结
1. D&C将问题逐步分解。使用D&C处理列表时,基线条件可能是空数组或者只包含一个元素的数组。
2、实现快速排序时,请随机的选择使用基准值的元素,快速排序的平均运行时间为O(n log n)。
3、大O表示法中的常量有时候事关重大,这就是快速排序比合并排序快的原因所在。
4、比较简单的查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n )的速度比O(n)快的多。