美文网首页算法提高之LeetCode刷题
数组中最小的k个数字【排序,最大堆,Quick Select算法

数组中最小的k个数字【排序,最大堆,Quick Select算法

作者: 明日大佬cc | 来源:发表于2020-01-12 04:13 被阅读0次

题目:

输入n个数,找出其中最小的k个数(k<=n)。

思路:

思路一:

将n个数排序,输出前k个。时间复杂度为O(nlogn)。当k比较大的时候(比如k>n/2),这种方法是一种不错的方法,但是在k比较小的时候,我们并不关心k位之后的数字的顺序,我们甚至也不关心前k个数字的顺序,这种方法带来了额外的操作,所以很显然时间上还有额外的优化空间。

思路二:

维护一个容量为k最大堆,将n个数入堆,最后堆中剩的k个数字就是最小的k个数。维护堆的时间复杂度为logk,需要将n个数字依次入堆,所以这种方法的时间复杂度为O(nlogk)。

思路三:

在方法二中,维护堆的过程依然可以得到前k个数字的顺序,而我们是不关心前k个数字的顺序的。用什么办法可以把数组分成两部分,而不关心每一部分的顺序呢?

当我们在进行快排的时候,我们每次会选择一个“哨兵”,小于哨兵的放在左边,大于哨兵的放在右边,那么如果哨兵的位置恰好为k,那不就刚好分好了吗?如果哨兵的位置不那么完美怎么办呢?递归进行下一次划分就好了!如果哨兵的位置>k,那么就递归处理左边的部分,否则处理右边的部分。

这种方法被称为“Quick Select”,与快排相比,快排需要每次递归处理两边的区间,而这种方法只处理一边,所以时间复杂度低于快排。利用主定理可以求出时间复杂度为O(n),在不关心前k个数字顺序时是最高效的算法之一。

代码:

import java.util.*;

public class Solution {

    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {

        ArrayList<Integer> ans = new ArrayList<>();

        if (k>input.length) {

        quickSelect(input,0,input.length-1,k-1);

        for (int i = 0;i<k;i++){

            ans.add(input[i]);

        }

        return ans;

    }

    public void quickSelect(int[] a,int l,int r,int k){

        if (l>=r) return;

        if (r == l+1){

            if (a[l]>a[r]){

                swap(a,l,r);

            }

            return;

        }

        int i = l;

        int j = r+1;

        int tmp = 0;

        while (i<j){

            i++;

            while (i<=r&&a[i]<a[l]) i++;

            j--;

            while (j>l&&a[j]>a[l]) j--;

            if (i<j) swap(a,i,j);

        }

        swap(a,l,j);

        if (j == k){

            return;

        }else if (j>k){

            quickSelect(a,l,j-1,k);

        }else{

            quickSelect(a,j+1,r,k);

        }

    }

    public void swap(int[] a,int x,int y){

        int tmp = a[x];a[x] = a[y];a[y] = tmp;

    }

}

相关文章

  • 数组中最小的k个数字【排序,最大堆,Quick Select算法

    题目: 输入n个数,找出其中最小的k个数(k<=n)。 思路: 思路一: 将n个数排序,输出前k个。时间复杂度为O...

  • 排序算法

    一、排序算法总结 排序算法题目 排序算法快速排序堆排序归并排序 应用最小K个数(TopK问题)215.数组中的第K...

  • 应用: 排序,从小到大用最大堆,从大到小用最小堆 选出元素中的 top k 个top k 个最小数:数组前k个元素...

  • 必会的QuickSelct算法 | partition函数,O(

    问题描述 给一个未排序数组,要求输出第k大(小)的值。 算法分析 算法基本思想就是Quick Sort中的part...

  • 2018-04-27 海量数字中找到最大/小的K个(TopK 问

    来自xie4ever假如业务场景需要在十亿个数字中找到最小k个的数字。设计算法。 排序方法。最容易想到肯定是排序了...

  • 数据结构

    排序算法 请写一个 min 函数,要求 min(numbers) 能返回数组 numbers 中的最小数字。 请写...

  • 算法-数组(三)

    最小的k个数 求子数组的最大和 把数组排成最小的数字 1.最小的k个数 问题描述:输入n个数字,找到数组中最小的k...

  • 排序

    初级排序算法 1.1 选择排序 思想 找到数组中最小的元素,然后和数组中第一个元素进行交换。然后找到剩下数中最小的...

  • 堆的应用

    堆排序 100个亿数中找出最小的前k个数(海量数据 Top k 问题)-->建大堆 100个亿数中找出最大的前k个...

  • 『算法』之 初级排序算法总结

    本篇文章同时收录在我的个人博客:『算法』之 初级排序算法总结 选择排序 一种最简单的排序算法:首先,找到数组中最小...

网友评论

    本文标题:数组中最小的k个数字【排序,最大堆,Quick Select算法

    本文链接:https://www.haomeiwen.com/subject/ophiactx.html