左程云算法通关024 随机选择算法

前置知识:算法讲解023 随即快速排序

无序数组中求第K大或者第K小的数字,需要寻找的是数组排序后第K大的数字,而不是第K个不同的数字。要求:时间复杂度O(n)

利用改写快排的方法,时间复杂度O(n),额外空间复杂度O(1)。

上面问题的解法就是随机选择算法,是常考内容!证明见算法导论9.2.

算法导论第九章,还有一个BFPTR算法,不用随机选择一个数的方式,时间复杂度也能到O(n),额外空间复杂度O(logn),这个算法很冷门,知道有即可。

我们利用改写快排方法:我们假设一个数组,要求第52大的数字,那么荷兰国旗问题划分之后我们看中间等于部分,下标有没有命中52,如果有,就说明我们随机选择的这个数字就是第52的数。

如果没有,那么是大了还是小了?这样我们就从双边变成了单边,这就是改写快排方法。

快排是O(nlogn),能满足我们这里要求的O(n)吗?

最好情况:选择的数字刚好处于中间位置,每次划分都能平均分左右,这样时间复杂度是n+n/2+n/4+...+n/2^n

最坏情况:要求第0大的数字,但是每次我都选择了第100大,第99大...这样就是O(n^2)。

这样概率的期望就是O(n)。

习题:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return randomizedSelect(nums,nums.length-k);
    }
    //如果对arr排序的话,第i位置的数字应该是什么?
    public int randomizedSelect(int[]arr,int i){
        int l=0;
        int r=arr.length-1;
        int ans=0;
        while(l<=r){
            int x=arr[l+(int)(Math.random()*(r-l+1))];
            partition(arr,l,r,x);
            if(i<first){
                r=first-1;
            }
            else if(i>last){
                l=last+1;
            }
            else{
                ans=arr[i];
                break;
            }
        }
        return ans;
    }
    public void partition(int[]arr,int l,int r,int temp){
        first=l;
        last=r;
        int i=l;
        while(i<=last){
            if(arr[i]==temp){
                i++;
            }
            else if(arr[i]<temp){
                swap(arr,first,i);
                first++;
                i++;
            }
            else{
                swap(arr,last,i);
                last--;
            }
        }
    }
    public int last,first;
    public void swap(int[]arr,int a,int b){
        int temp=arr[a];
        arr[a]=arr[b];
        arr[b]=temp;
    }

}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值