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

算法思想

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

主定理(master theorem)

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

a. 若 f ( n ) = O ( n l o g b a − ϵ ) , ϵ > 0 , 则 T ( n ) = Θ ( n l o g b a ) 若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 ) = Θ ( n l o g b a ) , 则 T ( n ) = Θ ( n l o g b a l o g n ) 若f(n)=\Theta(n^{log_ba}),则T(n)=\Theta(n^{log_ba}logn) f(n)=Θ(nlogba),T(n)=Θ(nlogbalogn)
c. 若 f ( n ) = Ω ( n l o g b a + ϵ ) , ϵ > 0 , 且 对 于 某 个 常 数 c < 1 和 所 有 充 分 大 的 n 有 a f ( n b ) ≤ c f ( 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 ( n 2 ) + n T(n) = T(\frac n 2)+n T(n)=T(2n)+n
由主定理可知,
a = 1 , b = 2 , l o g a b = 0 a=1,b=2,log_ab=0 a=1,b=2,logab=0
f ( n ) = n = Ω ( n ϵ ) , ϵ 取 1 , c 取 1 2 , 所 以 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];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值