import java.util.ArrayList; import java.util.Comparator; import java.util.PriorityQueue; /** * Created by Yang on 2017/4/18. * 输入n个整数,找出其中最小的K个数。 * 例如输入4,5,1,6,2,7,3,8这8个数字, * 则最小的4个数字是1,2,3,4,。 */ public class KLeastNumbers { /** * O(nlogk)的算法,特别适合处理海量数据 * 基于堆或者红黑树 * @param array * @param k * @return */ public ArrayList<Integer> getLeastNumbers(int[] array, int k) { if(array == null || array.length == 0 || k > array.length || k <= 0) { return new ArrayList<>(); } PriorityQueue<Integer> kLeastNumbers = new PriorityQueue<>(k, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); } }); for (int i = 0; i < array.length; i++) { if(kLeastNumbers.size() < k) { kLeastNumbers.offer(array[i]); } else { if(kLeastNumbers.peek() > array[i]) { kLeastNumbers.poll(); kLeastNumbers.offer(array[i]); } } } return new ArrayList<>(kLeastNumbers); } /** * O(n)的算法,只有当我们可以修改输入的数组时可用 * 基于Partition函数 * @param array * @param k * @return */ public ArrayList<Integer> getLeastNumbers1(int[] array, int k) { ArrayList<Integer> res = new ArrayList<>(); if(array == null || array.length == 0 || k > array.length || k <= 0) { return res; } int lo = 0; int hi = array.length - 1; int index = partition(array, lo, hi); while(index != k-1) { if(index > k-1) { hi = index - 1; index = partition(array, lo, hi); } else { lo = index + 1; index = partition(array, lo, hi); } } for (int i = 0; i < k; i++) { res.add(array[i]); } return res; } private int partition(int[] array, int lo, int hi) { if(array == null || array.length == 0 || lo < 0 || hi >= array.length || lo > hi) { //TODO 抛出异常 return -1; } // 随机选取枢纽元素,避免最坏情况 int pivotIndex = lo + (int)Math.random() * (hi - lo); swap(array, pivotIndex, hi); int small = lo - 1; for(int i = lo; i < hi; i++) { if(array[i] < array[hi]) { small++; if(small != i) { swap(array, i, small); } } } small++; swap(array, small, hi); return small; } private void swap(int[] array, int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } public static void main(String[] args) { KLeastNumbers kLeastNumbers = new KLeastNumbers(); int[] array = new int[]{4,5,1,6,2,7,3,8}; System.out.println(kLeastNumbers.getLeastNumbers(array, 4)); System.out.println(kLeastNumbers.getLeastNumbers1(array, 4)); array = new int[]{4,5,1}; System.out.println(kLeastNumbers.getLeastNumbers(array, 4)); System.out.println(kLeastNumbers.getLeastNumbers1(array, 4)); array = new int[]{4,5,1}; System.out.println(kLeastNumbers.getLeastNumbers(array, 3)); System.out.println(kLeastNumbers.getLeastNumbers1(array, 3)); array = new int[]{}; System.out.println(kLeastNumbers.getLeastNumbers(array, 4)); System.out.println(kLeastNumbers.getLeastNumbers1(array, 4)); array = null; System.out.println(kLeastNumbers.getLeastNumbers(array, 4)); System.out.println(kLeastNumbers.getLeastNumbers1(array, 4)); } }