剑指offer系列之二十八:最小的k个数

题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

对于此题,我觉得使用Java实现的话(所有OJ的代码都是使用Java实现的),实在是没有什么难度,就是一个简单的Collections函数的调用嘛,然而就是这么简单的一题,我居然提交代码提交了三次才被AC,实在是郁闷啊。主要的原因在于对边界条件的处理不是很好,简单而言就是代码不够健壮。还是言归正传,说说这题的思路吧:由于是n个整数,我们完全可以使用Java API中的函数完成这一功能,首先把数组中的元素添加到list集合对象中,然后调用Collections.sort()函数,完成排序(这个过程的时间复杂度是 O(nlogn) ,因为该函数的实现采用了快速排序算法),然后把list集合中除前k个数删掉,这样就返回了最小的k个数。

下面是基于这种思路代码实现(已被牛客AC):

package com.rhwayfun.offer;

import java.util.ArrayList;
import java.util.Collections;

public class GetLeastKNumbers {

    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        //注意边界条件的处理,很重要!
        if(input == null || k <= 0 || input.length == 0 || k > input.length) return list;
        for (int i = 0; i < input.length; i++) {
            list.add(input[i]);
        }
        //排序
        Collections.sort(list);
        if(k >= input.length){
            return list;
        }
        //移除后面的元素
        while(list.size() > k){
            list.remove(k);
        }
        return list;
    }

    public static void main(String[] args) {
        int[] input = new int[]{4,5,1,6,2,7,3,8};
        ArrayList<Integer> list = new GetLeastKNumbers().GetLeastNumbers_Solution(input, 8);
        System.out.println(list);
        System.out.println(0x8000000);
    }
}

下面介绍一种书上的第二种思路:创建一个用于保存最小k个数的容器,第一步是放入k个元素,第二步是比较容器中最大的数与当前数组遍历的那个数的大小,如果容器中最大的数比当前遍历的数大,就移除该数,并放入当前遍历的那个数。这样整个循环结束的时候,容器中就是最小的k个数了。下面是基于这种思路的实现算法:

public ArrayList<Integer> GetLeastNumbers_Solution2(int[] input, int k) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        if(input == null || k <= 0 || input.length == 0 || k > input.length) return list;
        //创建一TreeSet集合,因为TreeSet默认就是从小到大排序的
        TreeSet<Integer> s = new TreeSet<Integer>();
        for (int i = 0; i < input.length; i++) {
            if(s.size() < k){
                s.add(input[i]);
            }else{
                if(input[i] < s.last()){
                    s.remove(s.last());
                    s.add(input[i]);
                }
            }
        }
        //循环结束,s中已经保存了前k个最小的数,只需要迭代放入ArrayList中即可
        Iterator<Integer> it = s.iterator();
        while(it.hasNext()){
            list.add(it.next());
        }
        return list;
    }

你可能感兴趣的:(剑指offer系列之二十八:最小的k个数)