17.14. 最小K个数

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

面试题 17.14. 最小K个数

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4] 提示:

  • 0 <= len(arr) <= 100000
  • 0 <= k <= min(100000, len(arr))

解题思路

通过快速选择,我们可以将数组划分成两个区间A[l,i],B[i+1,r],A区间的所有元素均小于B区间

  • 如果k刚好就是A区间的长度的话,说明我们已经找到了最小的k个数字
  • 如果k大于A区间长度的话,说明我们要找的除了整个A区间以外,还有B区间的一部分元素
  • 如果k小于A区间长度的话,说明我们需要找的数全部在A区间里面

代码

class Solution {
    public int[] smallestK(int[] arr, int k) {

        int[] res=new int[k];
        int l=0,r=arr.length-1,w=k;
        while(l<r){
            
        int i=partition(arr,l,r);
        int n=i-l+1;
        if(n==k)
        {
            break;
        }else if(n<k){
            l=i+1;
            k-=n;
        }else {
            r=i;
        }
        }
         System.arraycopy(arr,0,res,0,w);
        return res;
    }
    public int partition(int[] arr, int l,int r) {
        int t=arr[l];
        while(l<r)
        {
            while(l<r&&arr[r]>=t)
                r--;
            arr[l]=arr[r];
            while(l<r&&arr[l]<=t)
                l++;
            arr[r]=arr[l];
        }
        arr[l]=t;
        return l;
        
    }
}
复制代码
  • 时间复杂度:期望为 O(n)

最坏情况下的时间复杂度为 O(n^2)。情况最差时,每次的划分点都是最大值或最小值,一共需要划分 n - 1 次,而一次划分需要线性的时间复杂度,所以最坏情况下时间复杂度为 O(n^2)。

  • 空间复杂度:期望为 O(logn),递归调用的期望深度为 O(logn),每层需要的空间为O(1),只有常数个变量。

最坏情况下的空间复杂度为 O(n)。最坏情况下需要划分 n 次,即 partition函数递归调用最深 n−1 层,而每层由于需要 O(1) 的空间,所以一共需要 O(n) 的空间复杂度。

猜你喜欢

转载自juejin.im/post/7016960017144217637