剑指offer40-最小的k个数

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

维持一个容量为k大根堆,将数组剩下的元素依次与堆顶比较,比堆顶小就加入堆。

/**
 * @param {number[]} arr
 * @param {number} k
 * @return {number[]}
 */
var makeHeap=function(arr,length){
    let i=Math.floor(length/2)-1;
    while(i>=0){
        let j=(i+1)*2-1,index=i,ai=arr[i];
        while(j<length){
            if(j+1<length&&arr[j+1]>arr[j]){
                j++;
            }
            if(arr[j]>ai){
                arr[index]=arr[j];
                index=j;
                j=(j+1)*2-1;
            }else{
                break;
            }
        }
        arr[index]=ai;
        i--;
    }
}
var siftDown=function(arr,length){
    let j=1,index=0,ai=arr[0];
    while(j<length){
        if(j+1<length&&arr[j+1]>arr[j]){
            j++;
        }
        if(arr[j]>ai){
            arr[index]=arr[j];
            index=j;
            j=(j+1)*2-1;
        }else{
            break;
        }
    }
    arr[index]=ai;
}
var getLeastNumbers = function(arr, k) {
    let length=arr.length;
    makeHeap(arr,k);
    for(let i=k;i<length;i++){
        if(arr[i]<arr[0]){
            arr[0]=arr[i];
            siftDown(arr,k);
        }
    }
    return arr.slice(0,k)


};

时间复杂度O(nlogk)

快排变形

快排每次划分的中间值都不会再移动位置了,所以索引为K的即为第k+1小的元素,据此可以比较划分值得位置与K,调整下一次划分得区间直到划分值的索引为K .

class Solution:
    def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
        def partition(arr,left,right):
            if left>=right:
                return left
            x=arr[left]
            i,j=left,right
            while i<j:
                while i<j and arr[j]>=x:
                    j=j-1
                arr[i]=arr[j]
                while i<j and arr[i]<x:
                    i=i+1
                arr[j]=arr[i]
            arr[i]=x
            return i
        left=0
        right=len(arr)-1
        index=-1
        while index!=k:
            index=partition(arr,left,right)
            if index<k:
                left=index+1
            else:
                right=index-1
        return arr[0:k]

        

注意:以上代码都改变了原数组,如果不能原地修改,就把数组复制一下就好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值