题目:

输入n个整数,找出其中最小的k个数。例如输入4、 5、 1、 6、 2、 7、 3、 8这8个数字,则最小的4个数字是1、 2、 3、 4。

思路:O(n)的算法,只有当我们可以修改输入的数组是可用

经典常用的算法,快速排序的精髓利用快速排序划分的思想,每一次划分就会有一个数字位于以数组从小到达排列的的最终位置index;位于index左边的数字都小于index对应的值,右边都大于index指向的值;所以,当index > k-1时,表示k个最小数字一定在index的左边,此时,只需要对index的左边进行划分即可;当index < k - 1时,说明index及index左边数字还没能满足k个数字,需要继续对k右边进行划分

代码实现:

public ArrayList<Integer> getLeastNumbers(int nums[], int k){ArrayList<Integer> list = new ArrayList<Integer>();int lens = nums.length;if(nums == null || lens == 0 || k > lens || k <= 0){return list;}int start = 0;int end = lens - 1;int index = partition(nums, start, end);while(index != k-1){if(index > k-1){end = index - 1;index = partition(nums, start, end);}else{start = index + 1;index = partition(nums, start, end);}}for (int i = 0; i < k; i++) {list.add(nums[i]);}return list;
}
private int partition(int[] nums, int start, int end) { //快排int privotKey = nums[start];while(start < end){while(start < end && privotKey <= nums[end]){--end;}swap(nums, start, end);//交换位置,使大于privotkey的值位于数组右边while(start < end && privotKey >= nums[start]){++start;}swap(nums, start, end);//交换位置,使小于privotkey的值位于数组左边}return start;
}
private void swap(int[] nums, int start, int end) { //交换数组元素位置int temp = nums[start];nums[start] = nums[end];nums[end] = temp;
}
public static void main(String[] args) { //测试int nums[] = {4, 5, 1, 6, 2, 7, 3, 8};Main m = new Main();ArrayList<Integer> list = m.getLeastNumbers(nums, 4);for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}
}

思路:O(nlogk)的算法,特别适合处理海量数据

我们可以创建一个容量为k的数据容器来存储最小的k个数字,接下来我们每次从输入的n个整数中读入一个数。如果容器中已有的数字少于k个,则直接把这次读入的整数放入容器之中;如果容器中已有k个数字了(即容器满了),我们就不能再插入数字了,只能去替换容器中已有的数字。替换的规则是,我们拿待插入的数字和容器中k个数字中的最大值进行比较,如果大于容器中的最大值,则抛弃这个整数,否则用这个整数去替换这个数字。

故,容器满了之后,我们需要做3件事:一是在k个整数中找到最大数;二是有可能在这个容器中删除这个最大数;三是有可能会在这个容器中插入一个新数字。用二叉树实现这个容器,我们能在O(logk)时间内实现这三步操作。因此对于n个数字而言,总的时间效率就是O(nlogk)。

容器的实现用数据结构中的最大堆,因为其根结点的值永远是最大的结点值。我们用红黑树来实现我们的最大堆容器。而TreeSet类实现了红黑树的功能,它的底层是通过TreeMap实现的,TreeSet中的数据会按照插入数据自动升序排序。我们只需要将数据放入TreeSet中,其就会为我们实现排序。

代码实现:

public static ArrayList<Integer> getLeastNumbers(int []nums, int k){ArrayList<Integer> list = new ArrayList<Integer>();int lens = nums.length;if(nums == null || lens == 0 || k > lens || k <= 0){return list;}TreeSet<Integer> kSet = new TreeSet<Integer>();for (int i = 0; i < lens; i++) {if(kSet.size() < k){kSet.add(nums[i]);}else if(nums[i] < kSet.last()){kSet.remove(kSet.last());kSet.add(nums[i]);}}Iterator<Integer> iterator = kSet.iterator();while(iterator.hasNext()){list.add(iterator.next());}return list;
}

小思:

借助于一个容器来存储这k个最小的数,有两个优点:(1)没有修改输入的数据;(2)这个算法适合海量数据的输入。算法的题目可以改成从海量数据中找出k个最小的数。第一个利用快速排序的思想的时间复杂度为O(n),后一个借助于一个容器的思想的时间复杂度为O(nlogk)。

最小的k个数(Java)相关推荐

  1. 【剑指offer】面试题40:最小的k个数(java)

    输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = 2 输 ...

  2. 【Java】 剑指offer(40) 最小的k个数

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7 ...

  3. [剑指offer][JAVA][面试第40题][最小的k个数][快选][堆][BST]

    [问题描述]面试第40题 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 : 输入:arr ...

  4. 最小的k个数 java_【Java】 剑指offer(40) 最小的k个数

    本文参考自<剑指offer>一书,代码采用Java语言. 题目 输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 思 ...

  5. java笔试题:海量数据找最大或最小的k个数(堆排序)

    题目 海量数据找最大或最小的k个数,这里以找最小的K个数为例 堆排序 例如给一个数组nums[]这棵树就是完全二叉树,则: nums[i]的左节点为:num[2 * i + 1] nums[i]的右节 ...

  6. LeetCode_Heap_剑指 Offer 40. 最小的k个数 【堆,泛型实现,自定义比较器】【C++/java】【简单】

    目录 一,题目描述 英文描述 中文描述 示例与说明 二,解题思路 1,手动实现堆--C++泛型实现 2,手动实现堆--java泛型实现 3,快速使用堆--C++ 优先队列 pop_heap().pus ...

  7. 【剑指Offer】最小的k个数---大顶堆 Java

    题目:输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 求数组中最小(最大)的n个数通常可以使用大顶堆(小顶堆) ...

  8. Java实现寻找最小的k个数

    1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 解决方案 2.1 全部排序法 先对这n个整数进行快速排序,在依次输出前k个数. package com.liuzhen. ...

  9. 伍六七带你学算法 入门篇-最小的k个数

    java面试题-最小的k个数 难度-简单 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:a ...

最新文章

  1. C# 图片旋转360度程序
  2. memcached全面剖析–4. memcached的分布式算法
  3. 数据库主键和索引区别
  4. Java将hive数据导入到hdfs_sqoop数据导入到Hdfs 或者hive
  5. 计算机硬盘换,无需重新安装系统即可更换硬盘的方法(计算机无需重新安装系统即可更换硬盘)...
  6. android 歌词的显示不出来,网易云音乐歌词不显示怎么办 网易云显示不出歌词的解决方法...
  7. 百度AI身份验证(公安验证)接口开发
  8. leetcode 1175. Prime Arrangements 解法 python
  9. Scrapy 出现DEBUG:Filtered duplicate request
  10. java 极客漫画_漫画:Java如何实现热更新?
  11. ios wifi 定位_iOS中三种定位方式
  12. 为什么unity中我的模型是红颜色的
  13. A-level 课程:最受欢迎和最不受欢迎的学科
  14. 网络推广平台有哪些优势?
  15. WebServer应用示例2:Siri语音识别读取传感器数据 | ESP32轻松学(Arduino版)
  16. 数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已
  17. 前端三剑客之HTML入门教程
  18. 知识付费项目有哪些?
  19. 如何编译PHP源代码?
  20. 项目范围管理和时间管理

热门文章

  1. 轻松解决2013 lost connection to mysql server at ‘reading initial communication packet‘, system error: 0“
  2. 全国计算机二级抵免自考,自考计算机可以抵免吗?
  3. Scrapy部署蜘蛛爬虫项目
  4. 1051366-32-5,Balixafortide (POL6326),肽类 CXC chemokine receptor 4 (CXCR4) 的拮抗剂
  5. 我的Java乱卷之路
  6. Integrity check failed for “antd“ (computed integrity doesn‘t match our records
  7. uniapp模拟导航栏,自定义导航栏的使用
  8. 20191019 前端日报
  9. 安装oracle 10g XE后的提示
  10. mybatis关系映射之一对多和多对一