AC牛客 BM46 最小的K个数

简介: AC牛客 BM46 最小的K个数

BM46 最小的K个数

题目描述

描述

给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
数据范围:0≤k,n≤10000,数组中每个数的大小0≤val≤1000
要求:空间复杂度O(n) ,时间复杂度 O(nlogk)

示例1

输入:
[4,5,1,6,2,7,3,8],4 

返回值:
[1,2,3,4]

说明:
返回最小的4个数即可,返回[1,3,2,4]也可以 

示例2

输入:
[1],0

返回值:
[]

解题思路

解法1 排序然后取值

1.使用冒泡 or 快排 or 堆排序,进行数组排序
2.遍历数组,取出前面k小元素即可

解法2 时间复杂度为O(nlogk)的解法

1.使用冒泡,时间复杂度是o(n^2),堆排序和快排的时间复杂度是O(nlogn),解法要求的时间复杂度和快排很靠近,所以我们只需要考虑,如果优化快排
2.我们知道快排的思想,是每次选取一个基准值,然后将小于它的元素放到左边,大于它的元素放到右边,那么我们使用这个特性来优化
3.对比基准值的位置与k

  • 当基准值的位置等于k时,那么直接返回即可,不需要再进行排序,因为此时数组的前k个元素尽管无序,但是已经是最小的k个元素
  • 当基准值的位置大于k时,那么我们只需排序,基准值位置的前半部分即可
  • 当基准值的位置小于k时,那么我们只需排序,基准值位置的后半部分即可

反复上面的三个步骤,直到k==基准值的位置

实践代码

解法 1 代码

import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> res = new ArrayList<>();
        if (input == null || input.length <= 0 || k == 0) {
            return res;
        }

        quickSort(input, 0, input.length - 1);
        k = k > input.length ? input.length : k;
        for (int i = 0; i < k; i++) {
            res.add(input[i]);
        }
        return res;
    }

    private void quickSort(int[] input, int left, int right) {
        if (left < right) {
            int temp = input[left];
            int i = left;
            int j = right;
            while (left < right) {
                while (left < right && input[right] > temp) {
                    right--;
                }
                if (left < right) {
                    input[left] = input[right];
                }
                while (left < right && input[left] <= temp) {
                    left++;
                }
                if (left < right) {
                    input[right] = input[left];
                }
            }
            input[left] = temp;
            if (condition) {
                
            }
            quickSort(input, i, left - 1);
            quickSort(input, left + 1, j);
        }
    }

    private void bubbleSort(int[] input) {
        boolean swap = false;
        for (int i = 0; i < input.length; i++) {
            for (int j = 0; j < input.length - i - 1; j++) {
                if (input[j] > input[j + 1]) {
                    int temp = input[j];
                    input[j] = input[j + 1];
                    input[j + 1] = temp;
                    swap = true;
                }
            }
            if (!swap) {
                break;
            }
        }

    }
}

解法2 代码

import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> res = new ArrayList<>();
        if (input == null || input.length <= 0 || k == 0) {
            return res;
        }

        if (input.length > k) {
            quickSort(input, 0, input.length - 1, k);
        }
        
        k = k > input.length ? input.length : k;
        for (int i = 0; i < k; i++) {
            res.add(input[i]);
        }
        return res;
    }

    private void quickSort(int[] input, int left, int right, int k) {
        if (left < right) {
            int temp = input[left];
            int i = left;
            int j = right;
            while (left < right) {
                while (left < right && input[right] > temp) {
                    right--;
                }
                if (left < right) {
                    input[left] = input[right];
                }
                while (left < right && input[left] <= temp) {
                    left++;
                }
                if (left < right) {
                    input[right] = input[left];
                }
            }
            input[left] = temp;
            if (left == k) {
                return;
            } else if (left < k) {
                quickSort(input, left + 1, j, k);
            } else {
                quickSort(input, i, left - 1, k);
            }
        }
    }
}
目录
相关文章
|
7月前
【每日一题Day357】LC1155掷骰子等于目标和的方法数 | dp
【每日一题Day357】LC1155掷骰子等于目标和的方法数 | dp
63 0
|
算法 C++
剑指offer(C++)-JZ40:最小的K个数(算法-排序)
剑指offer(C++)-JZ40:最小的K个数(算法-排序)
华为机试HJ86:求最大连续bit数
华为机试HJ86:求最大连续bit数
华为机试HJ58:输入n个整数,输出其中最小的k个
华为机试HJ58:输入n个整数,输出其中最小的k个
|
存储
华为机试HJ15:求int型正整数在内存中存储时1的个数
华为机试HJ15:求int型正整数在内存中存储时1的个数
AC牛客 BM4 合并两个排序的链表
AC牛客 BM4 合并两个排序的链表
98 0
AC牛客 BM4 合并两个排序的链表
AC牛客 BM3链表中的节点每k个一组翻转
AC牛客 BM3链表中的节点每k个一组翻转
86 0
AC牛客 BM3链表中的节点每k个一组翻转
|
机器学习/深度学习 vr&ar
CF1561D Up the Strip (整除分块 dp 因子)
CF1561D Up the Strip (整除分块 dp 因子)
113 0
CF1561D Up the Strip (整除分块 dp 因子)
PTA 1023 组个最小数 (20 分)
给定数字 0-9 各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意 0 不能做首位)。
99 0
AC牛客 BM89 合并区间
AC牛客 BM89 合并区间
97 0

热门文章

最新文章