剑指offer40_最小的k个数-(java) 多解法

面试题40. 最小的k个数

注意leetcode和牛客网的区别!!!! 返回值的类型不一致;

题目

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

思路1 — 直接调用排序算法!!!

Array.sort(int[] a);其实现也是快速排序~

import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
    // 注意 牛客网中该题是返回AyyayList类,leetcode中返回的是数组int[];
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> list = new ArrayList<>();
        if(k > input.length) {
            return list;  // 注意边界,此题k大于数组长度时,返回空的ArrayList<Integer>
        }else{
            Arrays.sort(input);// O(nlogn);
            for(int i = 0; i < k; i++){
                list.add(input[i]);
            }
            return list;
        }
    }
}

Array.sort()使用注意:
若是基本类型,需要转化为对应的对象类型(如:int转化为Integer)Arrays.sort()可以排序基本对象类型,但是不可以使用基本数据类型。
Arrays.sort()默认的是升序排序,降序排序可采用Collection.sort()匿名内部类。
数组与list一样,需要遍历出来

思路2 — 优化 快速排序~~

  • 空间复杂度 O(1),不需要额外空间。
  • 时间复杂度:和快速排序类似。由于快速选择只需要递归一边的数组,时间复杂度小于快速排序,期望时间复杂度为 O(n),最坏情况下的时间复杂度为 O(n^2)
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
    // 注意 牛客网中该题是返回AyyayList类,leetcode中返回的是数组int[];
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> li = new ArrayList<Integer>();
        //哭晕系列!!! 注意边界条件~~~~~
        if(input.length == 0 || k > input.length || k == 0 || input == null ){
            return li;
        }else{
            int[] sort =  quickSelected(input, 0, input.length-1, k-1);
            for(int i = 0; i < k; i++){
                li.add(sort[i]);
            }
            return li; 
        }
        
    }
    

    public int[] quickSelected(int[] arr, int low, int high, int k){
        int j = quickSort(arr, low, high);
        // 只要切分位置刚好等于k,则切分位置左边的就是满足条件的最小的k个数
        if(j == k){
            return arr;
        }    
        // 如果切分位置大于k值,代表需要减小左边的切分区间,继续从左边找最小的k个数。
        if(j > k){
            return quickSelected(arr, low, j-1, k);
        }
        // 如果切分位置小于k,说明右边还要继续从小到大的排序。
        return quickSelected(arr, j+1, high, k);
    }
        
    // 快排切分, 每次切分都把比基数大的放在基数的右边,比基数小的放在技术左边。返回基数的切分位置。
    public int quickSort(int[] arr, int low, int high){
        int key = arr[low];
        int i = low;
        int j = high;
        while(i < j){
            while(key <= arr[j] && i < j){
                j--;
            }
            while(key >= arr[i] && i < j){
                i++;
            }
            if(i < j){
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        arr[low] = arr[j];
        arr[j] = key;
        return j;
    }
}

思路3 —大根堆~~

注意: 需要掌握queue数据结构, 以及PriorityQueue优先队列(通过二叉小顶堆实现),优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
import java.util.PriorityQueue;
public class Solution {
    // 注意 牛客网中该题是返回AyyayList类,leetcode中返回的是数组int[];
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> li = new ArrayList<Integer>();
        if(input.length < k || k == 0){
            return li;
        }
        
        Queue<Integer> heap = new PriorityQueue<>(k, (v1, v2) -> Integer.compare(v2, v1));
        
        for(int num: input){
            if(heap.isEmpty() || heap.size() < k || num < heap.peek()){
                heap.offer(num);
            }
            if(heap.size() > k){
                heap.poll();
            }
        }
        
        for(int e: heap){
            li.add(e);
        }
        return li;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章