最小的k个数(大根堆法)——剑指Offer

题目描述

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

题目分析

这个题主要是通过构建大根堆来实现的,首先构建大小为k的大根堆,这样数组中最大的k个数就在其中,然后和数组中的其他树进行比较:

如果数组中的数<大根堆堆顶,那么将这个数和大根堆堆顶进行交换,之后在进行大根堆顺序的调整,这样一直遍历,直到数组末尾。

最终大根堆中的k个数就是数组中最小的k个数。

详情请看代码注释。

代码

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) 
    {
        if(input.empty()||k==0||k>input.size())
            return vector<int>{};
        vector<int> result;
        for(int i=input.size()/2-1;i>=0;i--)
            adjustHeap(input,i,k);//构建大根堆
        //将第k+1个数到末尾和大根堆的k个数进行比较
        for(int i=k;i<input.size();i++)
        {
            if(input[0]>input[i])
            {
                int temp=input[i];
                input[i]=input[0];
                input[0]=temp;
                adjustHeap(input,0,k);//重新调整堆
            }
        }
        //构建最终的k个数
        for(int i=0;i<k;i++)
        {
            result.push_back(input[i]);
        }
        return result;
    }
    void adjustHeap(vector<int>&input,int i,int n)
    {
        int left=2*i+1;//i结点的左孩子
        int right=2*i+2;//i结点的右孩子
        int largest=i;//父结点,左孩子,右孩子中最大值的下标
        if(left<n&&input[left]>input[largest])
            largest=left;
        if(right<n&&input[right]>input[largest])
            largest=right;
        if(largest!=i)
        {
            int tem;
            tem=input[i];
            input[i]=input[largest];
            input[largest]=tem;
            adjustHeap(input,largest,n);//递归调用,调整最大堆
        }
    }
};
1. 树状大根堆 树状大根堆是一种二叉树,满足以下性质: 1. 每个节点的值都大于等于其子节点的值。 2. 树的最后一层节点都靠左排列。 在Python中,我们可以使用列表来表示二叉树,其中第i个元素的左子节点为2i,右子节点为2i+1,父节点为i//2。 以下是创建树状大根堆的代码: ```python class MaxHeap: def __init__(self, arr=None): self.heap = [0] if arr: self.heap.extend(arr) self._build_heap() def _build_heap(self): n = len(self.heap) - 1 for i in range(n // 2, 0, -1): self._heapify(i) def _heapify(self, i): n = len(self.heap) - 1 largest = i left = 2 * i right = 2 * i + 1 if left <= n and self.heap[left] > self.heap[largest]: largest = left if right <= n and self.heap[right] > self.heap[largest]: largest = right if largest != i: self.heap[i], self.heap[largest] = self.heap[largest], self.heap[i] self._heapify(largest) def push(self, val): self.heap.append(val) i = len(self.heap) - 1 while i > 1 and self.heap[i] > self.heap[i // 2]: self.heap[i], self.heap[i // 2] = self.heap[i // 2], self.heap[i] i //= 2 def pop(self): if len(self.heap) == 1: return None if len(self.heap) == 2: return self.heap.pop() root = self.heap[1] self.heap[1] = self.heap.pop() self._heapify(1) return root ``` 2. 堆排序 堆排序是一种排序算法,基于树状大根堆实现。其思路是先将数组构建成树状大根堆,然后将堆顶元素与最后一个元素交换,再将前面的元素重新构建成树状大根堆,重复此过程直到数组有序。 以下是堆排序的代码: ```python def heap_sort(arr): n = len(arr) heap = [0] + arr for i in range(n // 2, 0, -1): _heapify(heap, i, n) for i in range(n, 0, -1): heap[1], heap[i] = heap[i], heap[1] _heapify(heap, 1, i - 1) return heap[1:] def _heapify(heap, i, n): largest = i left = 2 * i right = 2 * i + 1 if left <= n and heap[left] > heap[largest]: largest = left if right <= n and heap[right] > heap[largest]: largest = right if largest != i: heap[i], heap[largest] = heap[largest], heap[i] _heapify(heap, largest, n) ``` 3. 取前k个值 在树状大根堆中,堆顶元素是最大的元素,可以通过不断取出堆顶元素来获得最大的k个元素。 以下是取前k个值的代码: ```python def top_k(arr, k): n = len(arr) heap = [0] + arr[:k] for i in range(k // 2, 0, -1): _heapify(heap, i, k) for i in range(k, n): if arr[i] > heap[1]: heap[1] = arr[i] _heapify(heap, 1, k) return heap[1:] ``` 以上是树状大根堆、堆排序和取前k个值的Python实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值