最小的K个数

题目地址: https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/

题目需要在无序的数组中查找出 最小的K个数,并且这K个数不要求有序输出

所以我们只需要得到 小于等于第K+1大 K-1 的数

复杂度分析: 因为我们是要找下标为k的元素,第一次切分的时候需要遍历整个数组 (0 ~ n) 找到了下标是 middle 的元素,假如 k 比 middle 小的话,那么我们下次切分只要遍历数组 (0 ~ k-1)的元素就行啦,反之如果 k 比 middle 大的话,那下次切分只要遍历数组 (k+1~n) 的元素就行啦,总之可以看作每次调用 partition 遍历的元素数目都是上一次遍历的 1/2,因此时间复杂度是 N + N/2 + N/4 + … + N/N = 2N, 因此时间复杂度是 O(N)。

核心的快速排序方法

 //主要方法
    int[] sort(int[] arr, int low, int high, int k){

       int middle = middleSort(arr,low,high);

       //如果middle与k相等 就直接返回middle左端的所有元素
       if(middle == k){
           return Arrays.copyOf(arr,middle + 1);
       }

      // 否则根据下标middle与k的大小关系来决定继续切分左段还是右段。
      return middle > k? sort(arr, low, middle - 1, k)
              : sort(arr, middle + 1, high, k);

    }
    //将middle左右的数组顺序调整好,并返回middle的位置
    int middleSort(int[] arr,int low, int high){
        //设置初始值为中轴
        int middleVal = arr[low];
        while(low < high){
            //从最右端往左遍历
            while(low < high && arr[high] >= middleVal)
                high--;
            arr[low] = arr[high];
            //从最左端往右遍历
            while(low < high && arr[low] <= middleVal)
                low++;
            arr[high] = arr[low];
        }
        arr[low] = middleVal;
        return high;
    }
}

最终代码

class Solution {

    public int[] getLeastNumbers(int[] arr, int k) {
        int[] arrMin = new int[k];
        if(k == 0 || arr.length == 0) return arrMin;

       //使用快排去切分
        return sort(arr, 0, arr.length - 1, k - 1);

    }

    //主要方法
    int[] sort(int[] arr, int low, int high, int k){

       int middle = middleSort(arr,low,high);

       //如果middle与k相等 就直接返回middle左端的元素
       if(middle == k){
           return Arrays.copyOf(arr,middle + 1);
       }

      // 否则根据下标j与k的大小关系来决定继续切分左段还是右段。
      return middle > k? sort(arr, low, middle - 1, k)
              : sort(arr, middle + 1, high, k);

    }
    //将middle左右的数组顺序调整好,并返回middle的位置
    int middleSort(int[] arr,int low, int high){
        //设置初始值为中轴
        int middleVal = arr[low];
        while(low < high){
            //从最右端往左遍历
            while(low < high && arr[high] >= middleVal)
                high--;
            arr[low] = arr[high];
            //从最左端往右遍历
            while(low < high && arr[low] <= middleVal)
                low++;
            arr[high] = arr[low];
        }
        arr[low] = middleVal;
        return high;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值