剑指offer-最小的K个数
Posted pathjh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer-最小的K个数相关的知识,希望对你有一定的参考价值。
题目:最小的K个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
1 import java.util.ArrayList; 2 import java.util.Comparator; 3 import java.util.PriorityQueue; 4 public class Solution { 5 public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { 6 ArrayList<Integer>result=new ArrayList<Integer>(); 7 int n=input.length; 8 if(k>n||k==0) return result; 9 PriorityQueue<Integer>maxHeap=new PriorityQueue<Integer>(k,new Comparator<Integer>(){ 10 @Override 11 public int compare(Integer o1,Integer o2){ 12 return o2.compareTo(o1); 13 } 14 }); 15 for(int i=0;i<n;i++){ 16 if(maxHeap.size()!=k){ 17 maxHeap.offer(input[i]); 18 }else if(maxHeap.peek()>input[i]){ 19 Integer tmp=maxHeap.poll(); 20 tmp=null; 21 maxHeap.offer(input[i]); 22 } 23 } 24 for(Integer integer:maxHeap){ 25 result.add(integer); 26 } 27 return result; 28 } 29 }
java优先队列回顾
java中提供了PriorityQueue,PriorityQueue是基于小顶堆实现的无界优先队列,这个优先队列中的元素可以默认自然排序(实现了Comparable接口或内建类型)或者通过提供的Comparator(比较器)在队列实例化的时进行排序。
优先队列的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。如果不指定初始大小,其默认的初始大小为11。
优先队列使用实例:
首先创建一个用户类Customer,它没有提供任何类型的排序。当我们用它建立优先队列时,应该为其提供一个比较器对象。
1 public class Customer { 2 3 private int id; 4 private String name; 5 6 public Customer(int i, String n){ 7 this.id=i; 8 this.name=n; 9 } 10 11 public int getId() { 12 return id; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 }
使用Java随机数生成随机用户对象。对于自然排序,我们使用Integer对象,这也是一个封装过的Java对象。
1 import java.util.Comparator; 2 import java.util.PriorityQueue; 3 import java.util.Queue; 4 import java.util.Random; 5 6 public class PriorityQueueExample { 7 8 public static void main(String[] args) { 9 10 //优先队列自然排序示例 11 Queue<Integer> integerPriorityQueue = new PriorityQueue<>(7); 12 Random rand = new Random(); 13 for(int i=0;i<7;i++){ 14 integerPriorityQueue.add(new Integer(rand.nextInt(100))); 15 } 16 for(int i=0;i<7;i++){ 17 Integer in = integerPriorityQueue.poll(); 18 System.out.println("Processing Integer:"+in); 19 } 20 21 //优先队列使用示例 22 Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator); 23 addDataToQueue(customerPriorityQueue); 24 25 pollDataFromQueue(customerPriorityQueue); 26 27 } 28 29 //匿名Comparator实现 30 public static Comparator<Customer> idComparator = new Comparator<Customer>(){ 31 32 @Override 33 public int compare(Customer c1, Customer c2) { 34 return (int) (c1.getId() - c2.getId()); 35 } 36 }; 37 38 //用于往队列增加数据的通用方法 39 private static void addDataToQueue(Queue<Customer> customerPriorityQueue) { 40 Random rand = new Random(); 41 for(int i=0; i<7; i++){ 42 int id = rand.nextInt(100); 43 customerPriorityQueue.add(new Customer(id, "Pankaj "+id)); 44 } 45 } 46 47 //用于从队列取数据的通用方法 48 private static void pollDataFromQueue(Queue<Customer> customerPriorityQueue) { 49 while(true){ 50 Customer cust = customerPriorityQueue.poll(); 51 if(cust == null) break; 52 System.out.println("Processing Customer with ID="+cust.getId()); 53 } 54 } 55 56 }
java中比较器的用法
在Java中有两个接口来支持这两个概念(Comparable和Comparator),这两个接口都有连个需要被实现的方法。分别是:
* java.lang.Comparable: int comparaTo(Object o1)
该方法将该对象(this)和o1进行对比,返回一个int型的值,意义如下(大小都是逻辑上的大小):
1. positive – 该对象比o1大
2. zero – 该对象和o1对象一样大
3. negative – 该对象比o1对象小
*java.util.Comparator: int compare(Object o1, Object o2)
该方法将o1和o2进行比较,返回一个int型的值,意义如下(大小都是逻辑上的大小):
- positive – o1 的值比 o2大
- zero – o1 的值和 o2 一样大
- negative – o1 的值比 o2小
java.util.Collections.sort(List)
和java.util.Arrays.sort(Object [])
这两个方法用把指定的list按照升序排列,这时list中的元素必须实现java.lang.Comparable
接口.
java.util.Collections.sort(List,Comparator)
和java.util.Arrays.sort(Object[], Comparator)
这两个方法在能够提供Comparator时对list进行排序。
关于比较器的返回值的正负与排序时升序还是降序的关系之前一直比较模糊,即什么时候返回1,就是升序,什么时候返回-1,也是升序,什么时候又是降序。
实质上
jdk
官方默认是升序,是基于:int compare(Object o1, Object o2)
< return -1 //也就是说o1<o2时,表明是升序,返回-1
= return 0
> return 1
官方的源码就是基于这个写的;可以理解为硬性规定。
也就是说,排序是由这三个参数同时决定的。
如果要降序就必须完全相反:
< return 1
= return 0
> return -1
给个例子说明下:
需求:设计一个学生类, 属性有姓名,年龄, 成绩,并产生一个数组,要求安照成绩从高到低,如果成绩相等则由年龄由低到高排序。
实现代码:
1 import java.util.Arrays; 2 class Student implements Comparable<Student>{ 3 private String name; 4 private int age; 5 private float score; 6 public Student(String name, int age, float score) { 7 this.name = name; 8 this.age = age; 9 this.score = score; 10 } 11 public String toString() { 12 return name + " " + age + " " + score; 13 } 14 public int compareTo(Student stu) { 15 if(this.score > stu.score) { 16 return -1; 17 } else if(this.score < stu.score) { 18 return 1; 19 } else { 20 if(this.age > stu.age) { 21 return 1; 22 } else if(this.age < stu.age) { 23 return -1; 24 } else { 25 return 0; 26 } 27 } 28 } 29 } 30 31 public class ComparableDemo { 32 public static void main(String[] args) { 33 Student students[] = {new Student("张三", 20, 90.0f), new Student("李四", 22, 90.0f), 34 new Student("王五", 20, 99.0f), new Student("赵六", 20, 70.0f), new Student("孙七", 22, 100.0f)}; 35 Arrays.sort(students); 36 for (Student stu: students) { 37 System.out.println(stu); 38 } 39 } 40 41 }
方法二:有空再补上
参考:java比较器原理
以上是关于剑指offer-最小的K个数的主要内容,如果未能解决你的问题,请参考以下文章