最小的k个数(java版)

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


【解题思路1】
//1.对数组按照从小到大的顺序,进行全排序。
//2.取数组的前k个节点
//3.注意输入的k的边界情况

【源码1】

import java.util.ArrayList;
import java.util.Arrays;

public class Solution {
    public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
        if(input == null){
            return null;
        }
        int len=input.length;
        ArrayList arr = new ArrayList();
        if(len == 0 || k==0 || k>len){
            return arr;
        }
        Arrays.sort(input);
        for(int i=0; ireturn arr;
    }
}

a. 注意测试用例的边界情况。输入的数组可能为null,也可能为空数组,即长度为零。
b. k>input.length 的情况可能存在,或者k=0。


【解题思路2】在“思路1”的基础上改进一下
//1. 采用冒泡排序的思想,只冒泡k次。
//2. 冒泡出来的k个最小值,即符合要求

【源码2】

import java.util.ArrayList;

public class Solution {
   public static ArrayList GetLeastNumbers_Solution(int [] input, int k) {
        if(input == null){
            return null;
        }
        int len = input.length;
        ArrayList al = new ArrayList();
        if (k > len) {
            return al;
        }
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < len - i - 1; j++) {
                if (input[j] < input[j + 1]) {
                    int temp = input[j];
                    input[j] = input[j + 1];
                    input[j + 1] = temp;
                }
            }
            al.add(input[len - i - 1]);
        }
        return al;
    }
}

【解题思路3】
//1. 利用简单选择排序,每次挑选当前无序区里最小的值出来。
//2. 进行k次简单选择排序,得到要求的值。

【源码3】

import java.util.ArrayList;

public class Solution{
    public static ArrayList GetLeastNumbers_Solution(int [] input, int k) {
        if(input == null){
            return null;
        }
        int len = input.length;
        ArrayList arr = new ArrayList();
        if (k > len || k==0 || len==0) {
            return arr;
        }
        int min = 0;                                //标记最小元素的下标
        for (int i = 0; i < k; i++) {
            min = i;
            for (int j = i+1; j < len; j++) {
                if (input[j] < input[min]) {
                    min = j;
                }
            }
            int temp = input[i];
            input[i] = input[min];
            input[min] = temp;
            arr.add(input[i]);
        }
        return arr;
    }
}

【解题思路4】
//1. 利用堆排序,O(N logK),适合处理海量数据。遍历输入数组,将前k个数插入到推中。
//2. 继续从输入数组中读入元素做为待插入整数,并将它与堆中最大值比较:如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还大,则抛弃这个数,继续读下一个数。
//3. 这样动态维护堆中这k个数,以保证它只储存输入数组中的前k个最小的数,最后输出堆即可。

【源码4】

import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
   public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
       ArrayList result = new ArrayList();
       int length = input.length;
       if(k > length || k == 0){
           return result;
       }
        PriorityQueue maxHeap = new PriorityQueue(k, new Comparator() {

            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });
        for (int i = 0; i < length; i++) {
            if (maxHeap.size() != k) {
                maxHeap.offer(input[i]);
            } else if (maxHeap.peek() > input[i]) {
                Integer temp = maxHeap.poll();
                temp = null;
                maxHeap.offer(input[i]);
            }
        }
        for (Integer integer : maxHeap) {
            result.add(integer);
        }
        return result;
    }
}

【解题思路5】
//1. 利用快速排序中的获取分割(中轴)点位置函数getPartitiion。
//2. 基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边。
//3. 调整之后,位于数组左边的k个数字就是最小的k个数字(这k个数字不一定是排序的)。复杂度为O(N)。

【源码5】

链接:https://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf
来源:牛客网

import java.util.ArrayList;
public class Solution {
    public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList aList = new ArrayList();
        if(input.length == 0 || k > input.length || k <= 0)
            return aList;
        int low = 0;
        int high = input.length-1;
        int index = Partition(input,k,low,high);
        while(index != k-1){
            if (index > k-1) {
                high = index-1;
                index = Partition(input,k,low,high);
            }else{
                low = index+1;
                index = Partition(input,k,low,high);
            }
        }
        for (int i = 0; i < k; i++) 
            aList.add(input[i]);
        return aList;
    }
     
    int Partition(int[] input,int k,int low,int high){
        int pivotkey = input[k-1];
        swap(input,k-1,low);
        while(low < high){
            while(low < high && input[high] >= pivotkey)
                high--;
            swap(input,low,high);
            while(low < high && input[low] <= pivotkey)
                low++;
            swap(input,low,high);
        }
        return low;
    }
 
 
    private void swap(int[] input, int low, int high) {
        int temp = input[high];
        input[high] = input[low];
        input[low] = temp;
    }
}

【解题思路6】
//利用红黑树,因为C++中有该数据结构的实现multiset,而java中并没有。所以在此不再赘述。
可参考C++的实现。

【源码6】

参考
https://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf

你可能感兴趣的:(算法-剑指Offer-java)