求数组中第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 
#include 
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<3)<return 0;
}

你可能感兴趣的:(algorithms)