二分思想和分治法

二分思想和分治法
  如果你对概念很敏感,会马上意识到这两者的细微不同:二分搜索每次都要舍弃一半,从留下的一半中寻找目标;而分治法把一个大问题分成两个或多个小问题,递归地求这些小问题的解,最后再把它们小心谨慎的合并起来,并且要仔细考虑合并时产生的新的情况。这当然没有错,但你也马上会从这里意识到两者的巨大联系。就拿选取数组中第k个最小的数的算法来说,有一个版本便是从快速排序中修改而来:划分后,舍弃掉不存在的区间,对剩余部分迭代(后文将进行讲解),而快速排序是分治法的典型代表。


  正式地把这个问题叙述为:


在O(n)时间内从数组x[0...n-1]中找出第k个最小的元素。可以改变原数组中元素的位置。


  下面这段代码就是从快速排序中修改而来,同时考虑到了随机选择划分元素的问题。


int partition(int *array, int p, int r) {
    int x,i,j;
    x = array[r];
    i = p-1;
    for (j=p;j<=r-1;j++) {
        if (array[j]<= x) {
            i++;
            swap_value(array+i,array+j);
        }
    }
    swap_value(array+i+1,array+r);
    return i+1;
}


int random_select(int *array, int p, int r, int i) {
    int q,k;
    if (p == r)
        return array[p];
    q = random_partition(array,p,r);
    k = q-p+1;
    if (i == k)
        return array[q];
    else if (i<k)
        return random_select(array, p, q-1, i);
    else
        return random_select(array, q+1, r, i-k);
}




 


扩展:(《续》习题15.2)如何从一个3元数组中选出第2小的?如果从1000000个中选出1000个最小元素、且输入存储在磁带上呢?


分析:前者至多只需3次比较:1和2、1和2中最大的和3、1和2中最小的和3;后者是遍历时用1000大小的最大堆保存1000个当前最小的即可。其实前者是为了说明,如果问题只有几步就可以解决,根本没必要使用复杂的递归函数,直接解就是了;而后者是因为磁带进行随机I/O不方便而已,否则,直接用K=1001划分,那么K前面的1000个就是所求的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值