A题之找K个最小的数

剑指offer上的一道题:输入n个整数,找出最小的k个数。例如输入4、5、1、6、2、7、3、8共8个数,最小的4个数为:1、2、3、4。

分析:

解法一:

可以把它看车数组排序问题,先对数组排序,再取数组前k个数。各个排序算法中,快排是性价比比较高的了,时间事件复杂度为O(n*logn)。还有没有其他解法呢?

解法二:

快排思想派上用场了。快排算法中,我们通常要找一个参考元素,针对这个元素把数组分为俩个子数组。元素左边的子数组小于该元素,元素右边的子数组小于该元素。对了!只要找到一个元素使得他左边的子数组个数为k就可以了。

这种解法最坏的时间复杂度也才O(n*logn),是不是比第一种解法好多了!

解法三:

怎么能忘了堆排呢,构建一个k个元素的小顶堆,不停的往里面插入元素。最后堆里的元素就是我们要求的K个最小元素。这种解法的好处是没有移动数组中的元素。但却开辟了额外的空间。

基于解法三的Java解法:

构建K个堆的过程太过复杂了,Java里提供了很多集合,我们可以用起来撒!

下面的代码就是我利用TreeSet构建的一个小顶堆,为什么要用TreeSet?嘿嘿,不深究了,不同的同学可以看看红黑树。TreeSet默认的排序是一个由大到小的二叉树,怎么办呢?重写Comparable接口。

1)自定义一个类MyInteger,将int封装进去;

2)自定义MyInteger实现Comparable接口,大小关系颠倒;

3)将数组插入TreeSet,读取前K个数组元素即可;

import java.util.Comparator;

import java.util.Iterator;

import java.util.TreeSet;

public class KMinNumber

{

static class MyInteger implements Comparable<MyInteger>

{

  Integer i;

public MyInteger(int i)

{

this.i=i;

}

@Override

public int compareTo(MyInteger o)

{

// TODO Auto-generated method stub

if (i>o.getI())

{

return 1;

}

else if (i==o.getI())

{

return 0;

}

else

return -1;

}

@Override

public String toString()

{

// TODO Auto-generated method stub

return i.toString();

}

public Integer getI()

{

return i;

}

}

public static void main(String[] args)

{

  int[] a=new int[20];

for (int i = 0; i < a.length; i++)

{

a[i]=(int)(Math.random()*100);

System.out.print(a[i]+" ");

}

findKMin(a,5);

}

public static void findKMin(int[] a, int k)

{

  TreeSet<MyInteger> treeSet=new TreeSet<>();

for (int i = 0; i < a.length; i++)

{

MyInteger integer=new MyInteger(a[i]);

treeSet.add(integer);

}

System.out.println();

int i=0;

Iterator<MyInteger> iterator=treeSet.iterator();

while(i<k&&iterator.hasNext())

{

i++;

System.out.print(" "+iterator.next().toString());

}

}

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 16:29:52

A题之找K个最小的数的相关文章

k个最小的数

输入n个整数,输出k个最小的数.例如输入4,5,1,6,2,7,3,8这8个数,则最小的4个数字是1,2,3,4.利用堆排序 (1)遍历数组,将前k个数插入到堆中,使用multiset来实现堆(2)继续从输入数组中读入元素,作为待插入的整数,并将它与堆中的最大值进行比较,若待插入的值比这个最大值小,则用它替换最大值,否则抛弃这个数,继续读取下一个数.动态的维护堆中的数都是最小的,最后输出堆即可.multiset和set的区别是multiset允许元素重复.如果本题变为求k个最大的数,则将最大堆变

算法题19 把数组排成最小的数

题目 输入一个正整数数组,将他们连接起来排成一个数,输出所有排出的数字中最小的一个.例如:输入数组[32,321],输出所能排出的最小数为:32132.请给出该问题的算法. 分析 对于元素位置排列的问题,如a,b,我们希望找到一种排列规则,来确定我们所要得到的是a,b还是b,a. 题目要求得到所能排出的最小的数,那如a<b,则从常识来看ab<ba.这个比较规则到底正不正确呢?在剑指offer一书中有很好的证明 http://zhedahht.blog.163.com/blog/static/2

微软算法100题68 用数组排成最小的数

68.把数组排成最小的数.题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个.例如输入数组{32, 321},则输出这两个能排成的最小数字32132.请给出解决问题的算法,并证明该算法 1 package com.rui.microsoft; 2 3 import java.util.Arrays; 4 import java.util.Comparator; 5 6 public class Test68_Minimum { 7 8 public static

在集合中查找前k个最小的数

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define SIZE 10 5 6 int * k_thSmallest(int * arr, int len, int k_len); 7 8 void find(int* arr, int low, int high, int k_len); 9 10 void swap(int * a, int *b); 11 12 void printArr(int * arr, int le

剑指offer第32题:把数组排成最小的数及关于list.sort()和sorted( Iterable object )函数的相关知识

* 解题思路: * 先将整型数组转换成字符数组,然后将String数组排序,最后将排好序的字符串数组拼接出来.关键就是制定比较规则. * 排序规则如下: * 若ab > ba 则 a > b, * 若ab < ba 则 a < b, * 若ab = ba 则 a = b: * 其中比较规则如下: 自定义比较规则:比较两个字符串s1, s2大小时,先将它们拼接起来,比较s1+s2,和s2+s1哪个大,若s1+s2大,则s2应该放前面,反之亦然. * 比如"3"&l

IT公司100题-5-查找最小的k个元素

问题描述: 输入n 个整数,输出其中最小的k 个. 例如输入8, 7, 6, 5, 4, 3, 2, 1这8 个数字,则最小的3 个数字为3, 2, 1. 问题分析: 时间复杂度O(nlogn)方法: 对n个整数升序排序,取数组前面k个数就是最小的k个数,时间复杂度为O(nlogn),空间复杂度为O(1). 大顶堆,时间复杂度为O(nlogk): 我们可以采用大顶堆来保存最小的k个数,堆顶元素就是k个最小的数中最大的.新来一个元素的时候,与堆顶元素进行比较,如果比堆顶元素大,则直接丢弃.如果比堆

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

2014 HDU多校弟八场H题 【找规律把】

看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决,有规律的套公式 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring&g

找到图中最小有向圈的一个时间复杂度为O(mn)的算法

本文介绍一种在n个点 m条边并且没有负长度有向圈的有向图中找到最小有向圈的一个O(mn)时间复杂度的算法,这一结果是对于之前的最好的时间界O(mn+n^2 loglogn)的一个改进. 此算法首先在O(mn)时间复杂度内找到了具有最小平均长度λ^*的圈,因此它选择了点势函数来使得节约成本是λ^*或者更大.之后,该算法解决了所有点对之间的最短路问题,但是接下来将注意力集中于长度最多为nλ^*的最短路,将每一个源点的最短路时间的计算加速到O(m),这样所有的点时间的计算就到了O(mn). 同时,本文