用O(n)复杂度求第k大的值

本文深入探讨了快速选择算法的思想与应用,通过选取一个基准元素(pivot),将数组划分并找到第k大的元素。同时,详细解析了主定理(Master Theorem),这是一种用于分析递归算法复杂度的强大工具,适用于形式为T(n)=aT(n/b)+f(n)的递推表达式。

算法思想

取一个pivot,以pivot将原数组划分为两部分大小分别是x和y,确定了pivot的位置,现在知道pivot是第y+1大,如果k比y+1小,继续往右边找,如果k比y+1大,往左边找,如果k等于y+1,说明找到了。

主定理(master theorem)

假设有递推表达式 T(n)=aT(nb)+f(n)T(n)=aT(\frac n b)+f(n)T(n)=aT(bn)+f(n) ,其中nnn为问题规模,aaa为递推的子问题数量, nb\frac n bbn为每个子问题的规模(假设每个子问题的规模基本一样),f(n)f(n)f(n)为递推以外进行的计算工作。
a≥1,b>1a≥1,b>1a1b>1为常数,f(n)f(n)f(n) 为函数,T(n)T(n)T(n)为非负整数。则有以下结果(分类讨论):

a. 若f(n)=O(nlogba−ϵ),ϵ>0,则T(n)=Θ(nlogba)若f(n)=O(n^{log_ba-\epsilon}),\epsilon>0,则T(n)=\Theta(n^{log_ba})f(n)=O(nlogbaϵ),ϵ>0,T(n)=Θ(nlogba)
b. 若f(n)=Θ(nlogba),则T(n)=Θ(nlogbalogn)若f(n)=\Theta(n^{log_ba}),则T(n)=\Theta(n^{log_ba}logn)f(n)=Θ(nlogba),T(n)=Θ(nlogbalogn)
c. 若f(n)=Ω(nlogba+ϵ),ϵ>0,且对于某个常数c<1和所有充分大的n有af(nb)≤cf(n),那么T(n)=Θ(f(n))若f(n)=\Omega(n^{log_ba+\epsilon}),\epsilon>0,且对于某个常数c<1和所有充分大的n有af(\frac nb) \leq cf(n),那么T(n)=\Theta(f(n))f(n)=Ω(nlogba+ϵ),ϵ>0,c<1naf(bn)cf(n),T(n)=Θ(f(n))

证明

上面算法每次规模缩小一半,除此以外需要n次比较,所以可以写出递推表达式是T(n)=T(n2)+nT(n) = T(\frac n 2)+nT(n)=T(2n)+n
由主定理可知,
a=1,b=2,logab=0a=1,b=2,log_ab=0a=1,b=2,logab=0
f(n)=n=Ω(nϵ),ϵ取1,c取12,所以T(n)=Θ(n)f(n)=n=\Omega(n^\epsilon), \epsilon取1,c取\frac 12,所以T(n)=\Theta(n)f(n)=n=Ω(nϵ),ϵ1,c21T(n)=Θ(n)

代码实现

    private int partition(int[] nums, int l, int r) {
        int pivot = nums[l];
        while (l < r) {
            while (l < r && pivot <= nums[r]) r--;
            if (l < r) nums[l] = nums[r];
            while (l < r && pivot >= nums[l]) l++;
            if (l < r) nums[r] = nums[l];
        }
        nums[l] = pivot;
        return l;
    }

    public int findKthLargest(int[] nums, int l, int r, int k) {
        if (l == r && k == 1) return nums[l];
        int pivotIndex = partition(nums, l, r);
        int y = r - pivotIndex;
        if (k < y + 1) return findKthLargest(nums, pivotIndex + 1, r, k);
        else if (k > y + 1) return findKthLargest(nums, l, pivotIndex - 1, k - y - 1);
        else return nums[pivotIndex];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值