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
 {
  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 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 iterator=treeSet.iterator();
  while(i
  {
   i++;
   System.out.print(" "+iterator.next().toString());
  }
 }
}

你可能感兴趣的:(Java)