您的位置:首页 > 其它

MIT算法导论-第六讲-顺序统计问题

2015-12-01 13:51 239 查看

1. 最小值和最大值

在一个有n个元素的集合中,需要做n−1次比较才能确定其最小(大)元素。如果要同时找出最小值和最大值,通常的做法是对每一个输入的元素都与已知的min和max作比较,这样相当于独立完成两趟查找进行2(n−1)次比较。事实上,只要记录已知的min和max,每次取2个元素进行比较,然后较小的和min进行比较,较大的和max进行比较,这样就实现了对每两个元素进行3次比较,总共只需要3⌊n/2⌋次比较。这种算法虽然也是渐近为O(n)的算法,但从比较次数来看要比暴力求解快上约25%。

2. 随机化选择算法(选择第i小的算法)

随机选择算法是一种随机的分治算法,在进行主元划分之后,快速排序会递归处理划分的两边,而随机化选择算法只处理划分的其中一边。该算法的可以以O(n)的时间找到第i小的元素。

运行时间分析,平均时间为O(n),最好情况下就是每次选到的pivot都是数组的中位数,递归式为T(n)≤T(n/2)+Θ(n)。最坏情况下,递归式为T(n)=T(n-1)+Θ(n),时间复杂度可达到O(n^2),但出现最坏情况的概率非常小(1/n^n)。

代码:

int RandomPartition(int a[],int low,int high) {
if (low == high)
return low;
int index = GetRandomIndex(low, high);
int pivot = a[index];
Swap(a[index],a[high]);
int i = low-1;
for(int j=low;j<high;j++) {
if(a[j]<=pivot) {
Swap(a[i+1],a[j]);
}
}
Swap(a[i+1],a[high]);
return i+1;
}

int GetKMin(int a[], int length, int k) {
if (k > length)
k = length;
int low = 0, high = length - 1;
int index = RandomPartition(a, low, high);
print(a, length);
while (index != k - 1) {
if (index < k - 1)
low = index + 1;
else
high = index - 1;
index = RandomPartitionEnd(a, low, high);
}
return a[index];
}


3. 确定性选择算法(任何情况下,时间复杂度O(n))

从第二节可知随机化选择算法在最坏情况下的时间复杂度为O(n^2),这里的主要原因就是partition的划分不够理想,下面将要介绍一种任何情况下,时间复杂度都为O(n)的算法,它的主要思想就是对partition划分时,由原来的随机选择任意一个,升级为加以某种限制的选择。

算法流程如下:

1. 将n个元素划分为m=n/5组,每组5个元素(最多有一组由剩下的n mod 5个元素组成)

2. 对m组元素都进行插入排序,找出各组的中位数,共m个

3. m个中位数组成临时数组C,递归调用select找出C的中位数

4. 中位数的索引作为partition中的基准值

确定性选择算法的递归式

确定性选择算法最坏情况也可以达到O(n),但实际并没有随机算法快,因为它忽略的常数项更大,而且要多耗费存储空间。

视频里说到一个思想及其重要的,即:要想在分治法中得到线性的时间复杂度,则问题的子问题的size要小于n。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: