面试题30.最小的K个数

面试题30.最小的K个数

题目描述

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

思路1:

排序,然后取出前k个数字。这种方法的时间复杂度是O(nlogn)

思路2:

利用Partition算法,首先在数组中随机选择一个数字,然后把比它小的数字移到它的左边,把比它大的数字移到右边。全部移动完后:

  • 如果这个数字刚好处于第k个位置,那么它就是第k个数。
  • 如果这个数字在第k个位置的右边,说明第k个数在它左边,继续对左边查找
  • 如果这个数字在第k个位置的左边,说木第k个数在它右边,继续对右边查找

Partition算法参考:
https://so.csdn.net/so/search/s.do?q=Partition&t=blog&u=u010429424

思路3:

针对海量数据,可以使用堆排序的方法。

构建一个大顶堆,用k个数字初始化堆。然后对于后面的数字,与堆顶比较

  • 如果小于堆顶,则与堆顶替换,向下调整堆。
  • 反之,这个数肯定不是最小的k个数,跳过这个数

思路4:
利用java的TreeMap来实现,统计数字出现的次数,然后从小到大找到第k个数。

下面是思路1和思路4的代码

import java.util.*;

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        
        ArrayList<Integer> arr = new ArrayList<>();
        if(k > input.length || k < 1) {
            return arr;
        }
        
        // 解法1 排序 然后取前k个 O(nlogn)
        /*Arrays.sort(input);
        for(int i = 0; i < k; i++) {
            arr.add(input[i]);
        }*/
        
        // 解法4 使用红黑树 增删改查O(logk)
        TreeMap<Integer, Integer> treeMap = new TreeMap<>();
        for(Integer i : input) {
            if(treeMap.keySet().contains(i)) {
            	treeMap.put(i, treeMap.get(i) + 1);
            }else {
            	treeMap.put(i, 1);	
            }            
        }
        for(Integer i : treeMap.keySet()) {        	
            int n = treeMap.get(i);
        	for(int j = 0; j < n; j++) {
        		arr.add(i);
        		k--;
                if(k <= 0) return arr;
        	}
        }
        
        return arr;        
    }
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值