《剑指offer》:最小的K个数

这个题目的话,单纯看题目的名字就知道利用堆可以去解决。但是先讲一下另一种思路,就是将所有元素记录到自己的位置上,这样元素就会默认的从小到大进行排列,然后就可以找到了。代码如下:

    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<>();
        if(input.length < k || input.length == 0)
            return result;
        int max = input[0], min = input[0];
        for(int num : input) {
            if(num > max)
                max = num;
            if(num < min)
                min = num;
        }
        int[] flags = new int[max - min+1]; //找到最大最小值,申请空间存放每个元素相对位置
        for(int num : input) {
            flags[num-min]++;
        }
        for(int i = 0; i < flags.length; ++i) {
            if(flags[i] > 0) {
                if (result.size() == k)  //遍历前K个
                    return result;
                result.add(min+i);
            }
        }
        return result;
    }

当然这种解法空间复杂度比较高,一些特殊的数组例如最大最小值相差很大的可能造成很多空间的浪费,而且时间复杂度上也并没有多好,好几个O(n)。只是想提供一种这样的思路,即数组下标可以作为元素的索引。


当然,还是老老实实用堆做一遍比较好

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<>();
        if(input.length < k || input.length == 0 || k==0)
            return result;
        int[] heap = new int[k];
        for(int i = 0; i < k; ++i)
            heap[i] = input[i];
        for(int i = 0; i < k/2; ++i)  //对每个有叶子的进行调整
            siftDown(heap, i, k/2);
        for(int i = k; i < input.length; ++i) {  //只需要调整堆顶就可以了
            if (input[i] < heap[0]) {
                heap[0] = input[i];
                siftDown(heap, 0, k/2);
            }
        }
        for (int hea : heap)
            result.add(hea);
        return result;
    }
    //对于一个堆调整,index为当前节点下标,length为截至长度
    private void siftDown(int[] heap, int index, int length) {
        while(index < length) {
            int child = index*2 + 1;
            if(index*2+2 < heap.length && heap[index*2+2] > heap[child]) //找子树中较大的,将它上调,因为是个大顶堆
                child++;
            if(heap[index] < heap[child]) {
                swap(heap, index, child);
                index = child;
            } else {
                return;  //如果已经符合大顶堆了,则不用调整了,直接返回
            }
        }
    }
    
    private void swap(int[] heap, int index1, int index2) {
        int temp = heap[index1];
        heap[index1] = heap[index2];
        heap[index2] = temp;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值