Sword40——最小的k个数

Sword40——最小的k个数

方法1——大顶堆

  • 思路:使用自定义比较器接口的PriorityQueue实现大顶堆。首先将k个元素入堆,之后每当遍历一个元素,先与大顶堆的堆顶元素比较,当其大于堆顶元素时,直接跳过;当其小于堆顶元素时,则先从堆中出队,再将此元素入堆,最后将堆中元素遍历得出数组,返回即可
  • 特殊情况与临界分析:当k为0时的特殊情况
  • 终止条件:大顶堆中为空时
  • 步骤:
    • 定义存放结果的数组
    • k为0的判断
    • 构建大顶堆
    • 将k个元素入堆
    • 将之后元素入堆
      • 当前元素小于堆顶元素
        • 堆中弹出堆顶元素
        • 当前元素入堆
    • 将堆中元素存入结果数组
    • 返回结果数组
    public int[] getLeastNumbers(int[] arr, int k) {
        // 定义存放结果的数组
        int[] res = new int[k];
        // k为0的判断
        if (k == 0) {
            return res;
        }
        // 构建大顶堆
        PriorityQueue<Integer> heap = new PriorityQueue<>((n1, n2) -> n2 - n1);
        // 将k个元素入堆
        for (int i = 0; i < k; i++) {
            heap.offer(arr[i]);
        }
        // 将之后元素入堆
        for (int i = k; i < arr.length; i++) {
            // 当前元素小于堆顶元素
            if (arr[i] < heap.peek()) {
                // 堆中弹出对顶元素
                heap.poll();
                // 当前元素入堆
                heap.offer(arr[i]);
            }
        }
        // 将堆中元素存入结果数组
        for (int i = 0; i < k; i++) {
            res[i] = heap.poll();
        }
        // 返回结果数组
        return res;
    }

方法1——大顶堆

方法2——快排思想

  • 思路:
    • 快排思想选取基准元素进行比较
      • 当右侧不满足比基准元素要大
      • 左侧不满足比基准元素要小,
      • 则将二者进行交换;
      • 当左边界不小于右边界时,将基准元素回填
    • 此时比较左边界与k的大小
      • 左边界大于k,证明此时左侧个数大于k个,继续向左递归寻找
      • 左边界小于k,证明此时左侧个数小于k个,继续向右递归寻找
      • 左边界等于k,证明此时左侧个数恰好为k个,直接返回即可
  • 特殊情况与临界分析:数组个数小于等于k时直接返回,k为0时将包含在快排中
  • 终止条件:无
  • 步骤:
    • 数组个数小于等于k时,直接返回
    • 展开快排
    • 快排方法
      • 参数:原数组、k、左边界、右边界
      • 初始化左右指针、基准元素
      • 循环条件:左指针小于右指针
      • while循环对数组进行划分
        • 循环条件:左指针小于右指针,且右侧元素大于等于基准元素
        • while循环
          • 右指针前移
        • 循环条件:左指针小于右指针,且左侧元素小于等于基准元素
        • while循环
          • 左指针后移
        • 交换此时左右指针的元素
      • 基准元素回填
      • 比较左指针与k的三种情况
        • 当left大于k,继续向左快排查找
        • 当left小于k,继续向右快排查找
        • 当left等于时,即直接返回left左侧元素
    public int[] getLeastNumbers(int[] arr, int k) {
        // 数组个数小于等于k时,直接返回
        if (arr.length <= k) {
            return arr;
        }
        // 展开快排
        return quickSort(arr, k, 0, arr.length - 1);
    }
	// 快排方法
	private int[] quickSort(int[] arr, int k, int start, int end) {
        // 初始化左右指针、基准元素
        int left = start, right = end, pivot = arr[start];
        // while循环
        while (left < right) {
            // while循环
            while (left < right && arr[right] >= pivot) {
                right--;
            }
            // while循环
            while (left < right && arr[left] <= pivot) {
                left++;
            }
            // 交换此时左右指针的元素
            swap(arr, left, right);
        }
        // 基准元素回填
        swap(arr, left, start);
        // 比较此时左指针与k的情况
        // 当左指针大于k时
        if (left > k) {
            // 向左进行快排
            return quickSort(arr, k, start, left - 1);
        }
        // 当左指针小于k时
        if (left < k) {
            return quickSort(arr, k, left + 1, end);
        }
        // 当左指针等于k时
        return Arrays.copyOf(arr, k);
    }
	private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

方法2——快排思想

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值