ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

剑指 Offer 40. 最小的k个数

2022-01-31 23:01:43  阅读:140  来源: 互联网

标签:arr pq return Offer int 元素 个数 40 num


剑指 Offer 40. 最小的k个数

做这题有很多办法,如果内置了sort函数的语言,就比较简单,可以先排序,再取前k个数即可。

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] ans = new int[k];
        Arrays.sort(arr);
        for(int i = 0; i < k; i++) ans[i] = arr[i];
        return ans;
    }
}

时间复杂度为\(O(nlogn)\),空间复杂度为\(O(k)\)。

或者手写快排,这里正好复习一下快速排序的原理。

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] ans = new int[k];
        quickSort(arr, 0, arr.length - 1);
        for(int i = 0; i < k; i++) ans[i] = arr[i];
        return ans;
    }

    private void quickSort(int[] arr, int lo, int hi) {
        if(lo >= hi) return ;
        int l = lo - 1, r = hi + 1, pivot = arr[lo + hi >> 1];
        while(l < r) {
            do l++; while(arr[l] < pivot);
            do r--; while(arr[r] > pivot);
            if(l < r) {
                int tmp = arr[l];
                arr[l] = arr[r];
                arr[r] = tmp;
            }
        }
        quickSort(arr, lo, r);
        quickSort(arr, r + 1, hi);
    }
}

快排属于分治问题,分治一般分为3步:
①.划分为子问题;
②.递归处理子问题;
③.合并子问题;

void quick_sort(int q[], int l, int r)
{
    //递归的终止情况
    if(l >= r) return;
    //第一步:分成子问题
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while(i < j)
    {
        do i++; while(q[i] < x);
        do j--; while(q[j] > x);
        if(i < j) swap(q[i], q[j]);
    }
    //第二步:递归处理子问题
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
    //第三步:子问题合并.快排这一步不需要操作,但归并排序的核心在这一步骤
}

证明过程如下link
也可以使用大根堆,如果堆的大小小于k,则先将数字入堆,否则,比较当前元素和堆顶元素大小,堆顶是目前这7个元素中最大的元素,如果当前元素比堆顶的大,那么肯定不是前k个元素,直接跳过即可,如果比堆顶元素要小,先将堆顶元素出堆,这样才能使更小的元素入堆,最后重复上述过程,直到遍历完数组,再将堆中元素返回即可。

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if (k == 0 || arr.length == 0) {
            return new int[0];
        }
        // 默认是小根堆,实现大根堆需要重写一下比较器。
        Queue<Integer> pq = new PriorityQueue<>((v1, v2) -> v2 - v1);
        for (int num: arr) {
            if (pq.size() < k) {
                pq.offer(num);
            } else if (num < pq.peek()) {
                pq.poll();
                pq.offer(num);
            }
        }
        
        // 返回堆中的元素
        int[] res = new int[pq.size()];
        int idx = 0;
        for(int num: pq) {
            res[idx++] = num;
        }
        return res;
    }
}

时间复杂度\(O(nlogk)\),空间复杂度\(O(k)\)。

标签:arr,pq,return,Offer,int,元素,个数,40,num
来源: https://www.cnblogs.com/nullpointer-c/p/15858694.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有