求数组中第k个最大(小)的数,或k个最大(小)的数

题目描述

  1. Kth Largest Element in an Array(leetcode 215)
    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
  2. 最小的k个数(剑指offer)
    输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

解题思路

维护一个含K个元素的最大堆,根据最大堆的性质,堆顶是最大元素,若数组中剩余的数都大于堆顶元素,则堆中的元素为最小的K个数,堆顶元素为第K个小的数。
相反,若维护一个含K个元素的最小堆,遍历数组中剩余的元素,若大于堆顶,则将其赋值给堆顶元素,然后将其继续调整为最小堆,以此类推,直到数组中剩余的元素遍历完,则最终堆中元素为最大的K个数。

代码

// Kth Largest Element in an Array(leetcode 215)
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        if(k > nums.size())
            return -1;
        vector<int> heap;
        for(int i = 0; i < k; i++){
            heap.push_back(nums[i]);
        }
        // 建立一个最小堆
        for(int i = k/2-1; i>=0; i--)
            heap_adjust(heap, k, i);

        for(int i = k; i < nums.size(); i++){
            if(nums[i] > heap[0]){
                int temp = heap[0];
                heap[0] = nums[i];
                nums[i] = temp;
                heap_adjust(heap, k, 0);
            }
        }

        return heap[0];

    }
    void heap_adjust(vector<int> &nums, int n, int m){
      // 需要注意元素的索引:含n个元素的堆,从最后一个含叶子节点的节点开始遍历,
      // 该节点的值为n/2-1(由于初始下标从0开始)
      // 索引为m的节点的子节点为2*m+1, 2*m+2
        if(m <= n/2-1){
            int i = 2*m+1;
            if(i+1 < n && nums[i+1] < nums[i])//(注意要判断其右孩子是否存在)
                i++;
            if(nums[i] < nums[m]){
                int temp = nums[m];
                nums[m] = nums[i];
                nums[i] = temp;
                heap_adjust(nums, n, i);
            }
        }
    }
};
int main()
{
    Solution s = Solution();
    int a[] = {-1,2,0};
    vector<int> arr(a, a+sizeof(a)/sizeof(int));
    cout<<s.findKthLargest(arr, 3)<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值