问题描述:

输入n个整数,找出其中最小的k个数

思路1:

先排序,再取前k个

时间复杂度O(nlogn)

下面给出快排序的代码(基于下面Partition函数的方法)

  1. public void QuickSort(int[] arr, int start, int end){
  2. if(start == end){
  3. return;
  4. }
  5. int index = Partition(arr, start, end);
  6. if(index > start){
  7. QuickSort(arr, start, index - 1);
  8. }
  9. if(index < end){
  10. QuickSort(arr, index + 1, end);
  11. }
  12. }

相应的求最小的k个数的代码:

  1. static boolean InvalidInput = false;
  2. public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
  3. ArrayList<Integer> result = new ArrayList<Integer>();
  4. if(input == null || input.length == 0 || k > input.length || k <= 0){
  5. InvalidInput = true;
  6. return result;
  7. }
  8. int start = 0;
  9. int end = input.length - 1;
  10. QuickSort(input, start, end);
  11. for(int i = 0; i < k; i++){
  12. result.add(input[i]);
  13. }
  14. return result;
  15. }

思路2:(适合海量数据的输入)

—维护一个大小为k的容器。

—每次从输入整数读取一个数,如果容器中的数字少于k个,则直接加入,否则,找出容器中的最大值,与当前数字比较,若大于最大值,则不管,若小于,则替换最大值。

—时间复杂度O(n*log*k)

关于容器的数据结构的选择:

  1. 数组:查找最大值需要O(k)
  2. 最大堆:查找最大值需要O(1),但需要O(logk)时间完成删除及插入操作。
  3. 红黑树

思路3:基于Partition,会改变原始数组

  • 首先来看看Partition的原理与具体实现以及结果

Partition:思想是随机选择一个数,调整数组使得比所选数小的数字移动到数组的左边,比选择的数字大的数字大的数移到数组的右边。上一文中也用到了Partition的思想,但是并没有弄懂。下面对代码进行了详细的注释。

基于上述Partition函数的解析,我们能用它来实现本文中的求最小的k个数

思想:如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的数字都位于数组的右边。这样调整后,位于数组中左边的k个数字就是最小的k个数字。

缺陷:会改变原始数组;所得到的k个最小的数字不是有序的。

代码:

  1. import java.util.ArrayList;
  2. public class Solution {
  3. static boolean InvalidInput = false;
  4. public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
  5. ArrayList<Integer> result = new ArrayList<Integer>();
  6. if(input == null || input.length == 0 || k > input.length || k <= 0){
  7. InvalidInput = true;
  8. return result;
  9. }
  10. int start = 0;
  11. int end = input.length - 1;
  12. int index = Partition(input, start ,end);
  13. while(index != k-1){
  14. if(index > k - 1){
  15. end = index - 1;
  16. index = Partition(input, start ,end);
  17. }else{
  18. start = index + 1;
  19. index = Partition(input, start, end);
  20. }
  21. }
  22. for(int i = 0; i < k; i++){
  23. result.add(input[i]);
  24. }
  25. return result;
  26. }
  27. public int Partition(int[] arr, int start, int end){
  28. if(arr == null || arr.length == 0 || start < 0 || end < 0){
  29. return -1;
  30. }
  31. int index = start + (int)(Math.random() * ((end - start) + 1));//随机选择一个作为标杆的数字
  32. //将标杆放在数组最后一位
  33. int tmp = arr[index]; arr[index] = arr[end]; arr[end] = tmp;
  34. int small = start - 1;//small用来存储从右到左第一个小于标杆的数字的下标
  35. for(index = start; index < end; index++){
  36. if(arr[index] < arr[end]){//如果小于标杆
  37. small++;//更新第一个小的
  38. if(small != index){//如果当前遍历的不是第一个小的
  39. tmp = arr[index];arr[index] = arr[small];arr[small] = tmp;//将当前遍历的数字放在第一个小的位置上
  40. }
  41. }
  42. }
  43. //由于small指示的是从右到左第一个小于标杆的,而此时标杆还放在数组最后,因此,应该将标杆放在small后面一位。
  44. small++;
  45. tmp = arr[small];arr[small] = arr[end]; arr[end] = tmp;
  46. return small;//返回位置为所选择的标杆最后的位置
  47. }
  48. }

剑指Offer:面试题30——最小的k个数(java实现)的更多相关文章

  1. 剑指offer 面试题40. 最小的k个数

    O(N)划分法,注意这个方法会改变原数据(函数参数是引用的情况下)!当然也可以再定义一个新容器对其划分 要求前k小的数,只要执行快排划分,每次划分都会把数据分成大小两拨.直到某一次划分的中心点正好在k ...

  2. 剑指Offer - 九度1371 - 最小的K个数

    剑指Offer - 九度1371 - 最小的K个数2013-11-23 15:45 题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是 ...

  3. 剑指offer(29)最小的K个数

    题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 题目分析 这题有两种方法来做. 第一种就是基于partition的 ...

  4. 【剑指Offer】29、最小的K个数

      题目描述:   输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4.   解题思路:   本题最直观的解法就是将输入的n个整数排 ...

  5. 剑指offer面试题30:最小的k个数

    一.题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 二.解题思路 1.思路1 首先对数组进行排序,然后取出前k个数 ...

  6. 剑指offer面试题5 从头到尾打印链表(java)

    注:(1)这里体现了java数据结构与C语言的不同之处 (2)栈的操作直接利用stack进行 package com.xsf.SordForOffer; import java.util.Stack; ...

  7. 面试题30.最小的k个数

    题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8 这8个数字,则最小的四个数字为1,2,3,4, 这道题是典型的TopK问题,剑指Offer提供了两种方法来实现,一种方 ...

  8. 剑指offer——面试题30:包含min函数的栈

    #include"iostream" #include"stdio.h" using namespace std; ; ; template<typena ...

  9. 剑指offer面试题30.包含min函数的栈

    一开始写的垃圾代码,push和pop都是O(N) class Solution { public: vector<int> vec; int min_val=INT_MAX,min_cnt ...

随机推荐

  1. kernel/printk.c

    /* *  linux/kernel/printk.c * *  Copyright (C) 1991, 1992  Linus Torvalds * * Modified to make sys_s ...

  2. node.js Stream Buffer FsPromise

    Stream: 类似这样:a.pipe(b).pipe(c); 我想写一个b.所以: var rs=new (require('stream').Readable)(); var ws=new (re ...

  3. java程序员烂大街为何还不便宜?

    最近跟一朋友聊天,他是做c#开发的.他答应了老板带领一帮java工程师开发网站.披星戴月终于搞定,现在已经盈利.但是他公司的那帮搞c#的同事不淡定了. 在招聘java程序员的时候2年有开15k的.5年 ...

  4. C#生成随机字符串(数字,字母,特殊符号)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. ping指定地址

    最近用到相应功能,网上搜了下. 感谢网友的分享,原文链接如下:http://blog.csdn.net/nanfeiyannan/article/details/6636280 稍微更改了内容,代码如 ...

  6. Linux 下如何安装软件

    一.解析Linux应用软件安装包 通常Linux应用软件的安装包有三种: 1) tar包,如software-1.2.3-1.tar.gz.它是使用UNIX系统的打包工具tar打包的. 2) rpm包 ...

  7. bzoj1188 [HNOI2007]分裂游戏 博弈论 sg函数的应用

    1188: [HNOI2007]分裂游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 973  Solved: 599[Submit][Status ...

  8. LeetCode-Search a 2D Matrix

    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...

  9. 国内最新Unity3D视频教程合辑

    麦子学院最新Unity3D视频教程上线啦,此为现目前国内最全.最新Unity3D教程,分享给广大小伙伴,希望对大家学习Unity3D有帮助: 第一阶段:Unity3D概要及入门 零基础学C#开发 Un ...

  10. notepad++

    plugin-manager 先要保证plugin-manager是最新的,然后才能下载其它的插件进行安装. compare插件,文件对比工具