虽是读书笔记,但是如转载请注明出处http://segmentfault.com/blog/exploring/
..拒绝伸手复制党
以下内容是算法导论第九章的学习笔记。
1 求最大/小值
最优即O(n)
,比较n-1
次
2 同时求最大值和最小值
最直白的是O(2n)
,比较2n-2
次。还有一个优化的方法是成对的比较,把较小的与min比较,较大的与max比较。这样每对元素需要3
次比较
java
public int[] maxmin(int array[]){ int max = 0; int min = 0; int result[]={0,0}; //奇数个元素 if(array.length % 2 == 0){ if(array[0]>=array[1]){ max = array[0]; min = array[1]; } else{ max = array[1]; min = array[0]; } int time = array.length/2 -1; result = compare(array,0, min, max,time); } //偶数个元素 if(array.length %2 == 1){ min = max = array[0]; int time = array.length/2; result = compare(array,-1, min, max,time); } return result; } public int[] compare(int array[],int start,int min, int max,int time){ for(int i=1;i<=time;i=i+1){ int left = start+2*i; int right = start+2*i+1; if(array[left] <= array[right]){ if(array[left]<min){ min = array[left]; } if(array[right]>max){ max = array[right]; } } else if(array[left] > array[right]) if(array[right]<min){ min = array[right]; } if(array[left]>max){ max = array[left]; } } int result[] = new int[2]; result[0] = min; result[1] = max; return result; }
以期望线性时间做选择
性能:平均O(n)
最坏O(n^2)
借鉴快速排序每次partition的返回的结果是已排序的性质。
伪代码:
c
RANDOMIZED-SELECT ( A, p, r, i ) if p = r // 临界问题处理 then return A[p] q ← RANDOMIZED-PARTITION( A, p, r ) //进行划分,返回划分元下标 k ← q – p + 1 if i = k then return A[q]; else if i < k then return RANDOMIZED-SELECT ( A, p, q - 1, i ) else return RANDOMIZED-SELECT( A, q+1, r, i – k )
最坏情况线性时间的选择
类似RandomizedSelect算法,通过对输入数组进行递归划分来找出所求元素,但是算法保证每次对数组的划分是个好划分
step1 - step3 通过寻找中位数,使得对数组的划分是一个好的划分。
为什么要选择中位数作为划分的pivot number?
快速排序性能最好的时候是:数组的输入序列是均匀的[而非正序或者逆序],即每次递归都是:主元左端和右端的元素个数都一样,那么主元就是中位数。据此,我们可以改进 partition, 每次划分的位置都和中位数的位置相比,递归向下调用。
对快速排序最坏的时候的情况进行优化
快速排序对主元的划分决定了其运行时间,如果最坏是Ο(nlgn),那么就不允许出现极端划分情况。因为我们学习了最坏时间了线性的选择算法,我们何不利用其每次选择都选中位数作为主元的方法来避免极端情况的发生?既然每次都选择中位数作为主元,那么其递归运行时间总是 T(n)=2T(n/2)+Ο(n) 这样根据主方法 case 2 知道 T(n)=Ο(nlgn)。
想更一进步的支持我,请扫描下方的二维码,你懂的~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。