剑指Offer:面试题30——最小的k个数(java实现)
问题描述:
输入n个整数,找出其中最小的k个数
思路1:
先排序,再取前k个
时间复杂度O(nlogn)
下面给出快排序的代码(基于下面Partition函数的方法)
public void QuickSort(int[] arr, int start, int end){
if(start == end){
return;
}
int index = Partition(arr, start, end);
if(index > start){
QuickSort(arr, start, index - 1);
}
if(index < end){
QuickSort(arr, index + 1, end);
}
}
相应的求最小的k个数的代码:
static boolean InvalidInput = false;
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
if(input == null || input.length == 0 || k > input.length || k <= 0){
InvalidInput = true;
return result;
}
int start = 0;
int end = input.length - 1;
QuickSort(input, start, end);
for(int i = 0; i < k; i++){
result.add(input[i]);
}
return result;
}
思路2:(适合海量数据的输入)
—维护一个大小为k的容器。
—每次从输入整数读取一个数,如果容器中的数字少于k个,则直接加入,否则,找出容器中的最大值,与当前数字比较,若大于最大值,则不管,若小于,则替换最大值。
—时间复杂度O(n*log*k)
关于容器的数据结构的选择:
- 数组:查找最大值需要O(k)
- 最大堆:查找最大值需要O(1),但需要O(logk)时间完成删除及插入操作。
- 红黑树
思路3:基于Partition,会改变原始数组
- 首先来看看Partition的原理与具体实现以及结果
Partition:思想是随机选择一个数,调整数组使得比所选数小的数字移动到数组的左边,比选择的数字大的数字大的数移到数组的右边。上一文中也用到了Partition的思想,但是并没有弄懂。下面对代码进行了详细的注释。
基于上述Partition函数的解析,我们能用它来实现本文中的求最小的k个数
思想:如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的数字都位于数组的右边。这样调整后,位于数组中左边的k个数字就是最小的k个数字。
缺陷:会改变原始数组;所得到的k个最小的数字不是有序的。
代码:
import java.util.ArrayList;
public class Solution {
static boolean InvalidInput = false;
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
if(input == null || input.length == 0 || k > input.length || k <= 0){
InvalidInput = true;
return result;
}
int start = 0;
int end = input.length - 1;
int index = Partition(input, start ,end);
while(index != k-1){
if(index > k - 1){
end = index - 1;
index = Partition(input, start ,end);
}else{
start = index + 1;
index = Partition(input, start, end);
}
}
for(int i = 0; i < k; i++){
result.add(input[i]);
}
return result;
}
public int Partition(int[] arr, int start, int end){
if(arr == null || arr.length == 0 || start < 0 || end < 0){
return -1;
}
int index = start + (int)(Math.random() * ((end - start) + 1));//随机选择一个作为标杆的数字
//将标杆放在数组最后一位
int tmp = arr[index]; arr[index] = arr[end]; arr[end] = tmp;
int small = start - 1;//small用来存储从右到左第一个小于标杆的数字的下标
for(index = start; index < end; index++){
if(arr[index] < arr[end]){//如果小于标杆
small++;//更新第一个小的
if(small != index){//如果当前遍历的不是第一个小的
tmp = arr[index];arr[index] = arr[small];arr[small] = tmp;//将当前遍历的数字放在第一个小的位置上
}
}
}
//由于small指示的是从右到左第一个小于标杆的,而此时标杆还放在数组最后,因此,应该将标杆放在small后面一位。
small++;
tmp = arr[small];arr[small] = arr[end]; arr[end] = tmp;
return small;//返回位置为所选择的标杆最后的位置
}
}
剑指Offer:面试题30——最小的k个数(java实现)的更多相关文章
- 剑指offer 面试题40. 最小的k个数
O(N)划分法,注意这个方法会改变原数据(函数参数是引用的情况下)!当然也可以再定义一个新容器对其划分 要求前k小的数,只要执行快排划分,每次划分都会把数据分成大小两拨.直到某一次划分的中心点正好在k ...
- 剑指Offer - 九度1371 - 最小的K个数
剑指Offer - 九度1371 - 最小的K个数2013-11-23 15:45 题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是 ...
- 剑指offer(29)最小的K个数
题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 题目分析 这题有两种方法来做. 第一种就是基于partition的 ...
- 【剑指Offer】29、最小的K个数
题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 解题思路: 本题最直观的解法就是将输入的n个整数排 ...
- 剑指offer面试题30:最小的k个数
一.题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 二.解题思路 1.思路1 首先对数组进行排序,然后取出前k个数 ...
- 剑指offer面试题5 从头到尾打印链表(java)
注:(1)这里体现了java数据结构与C语言的不同之处 (2)栈的操作直接利用stack进行 package com.xsf.SordForOffer; import java.util.Stack; ...
- 面试题30.最小的k个数
题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8 这8个数字,则最小的四个数字为1,2,3,4, 这道题是典型的TopK问题,剑指Offer提供了两种方法来实现,一种方 ...
- 剑指offer——面试题30:包含min函数的栈
#include"iostream" #include"stdio.h" using namespace std; ; ; template<typena ...
- 剑指offer面试题30.包含min函数的栈
一开始写的垃圾代码,push和pop都是O(N) class Solution { public: vector<int> vec; int min_val=INT_MAX,min_cnt ...
随机推荐
- 声明提前js变量
声明提前问题相关 js的变量声明语句无论出现在何处,都会先与其他代码首先被执行,使用var声明关键词声明变量的 作用于是当前的执行上下文,有可能是外围函数,或者,当变量声明在函数体之外时,则为全局变量 ...
- 初涉hash
今天和朋友讨论一个问题 有两百亿个数,我给出一个数,找到这两百亿个数中两数相加等于它的组合.要求时间复杂度为线性,空间2G 解决思路是开一个hash表比如a[1000]将所有数存入hash表中,a[i ...
- 全面解析sizeof(上) 分类: C/C++ StudyNotes 2015-06-15 10:18 188人阅读 评论(0) 收藏
以下代码使用平台是Windows7 64bits+VS2012. sizeof是C/C++中的一个操作符(operator),其作用就是返回一个对象或者类型所占的内存字节数,使用频繁,有必须对齐有个全 ...
- 解决IAR无法跳转的问题
在工程的C编译器选项里的预编译添加$TOOLKIT_DIR$\inc可以搞定.
- 【原创】关于不同分支代码的Merge有了透彻的理解
多分支开发,Merge是一个绕不过的话题,不管是Git还是SVN,公司用的是SVN,之前对于SVN的Merge没有很好的研究,出了些状况,这个问题不解决,顺畅地进行多分支开发就是海市蜃楼,下定决心把这 ...
- 【转】windows server 2012清除并重建SID
windows server 2012清除并重建SID 2012-09-17 17:51:51 标签:SID windows server 2012 原创作品,允许转载,转载时请务必以超链接形式标明文 ...
- XSS的原理分析与解剖
0×01 前言: <xss攻击手法>一开始在互联网上资料并不多(都是现成的代码,没有从基础的开始),直到刺的<白帽子讲WEB安全>和cn4rry的<XSS跨站脚本攻击剖析 ...
- UIAlertView和UIActivityIndicatorView的使用
UIAlertView用来显示一个对话框,可以设置对话框的标题.文案.按钮的个数和文案,也可以通过实现delegate来监听按钮的的点击操作. 使用UIAlertView时需要注意: self.ale ...
- linux下重置mysql的root密码
# /etc/init.d/mysql stop # mysqld_safe --user=mysql --skip-grant-tables --skip-networking & # my ...
- MyBatis入门学习教程-实现关联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...