215. Kth Largest Element in an Array(数组中第k大元素)

215. Kth Largest Element in an Array(数组中第k大元素)

题目链接

https://leetcode.com/problems/kth-largest-element-in-an-array/description/

题目描述

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.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.

题目分析

这是一个非常常见的题目,解法少说也有五六种。我这里只介绍两种,一种是利用SQL写起来非常简单,几行代码就可以轻松搞定;另一种是时间复杂度较低,写起来略微复杂一点。

方法一:优先队列

算法描述
  • 遍历数组,维护一个长度不超过k的优先队列,当队列长度小于k时,当前元素进队;当队列长度等于k时,当前元素和队列中最小元素比较,若大于队列中最小元素,则最小元素出队,当前元素进队。
  • 遍历结束后,队列中的最小元素即位数组中第k大元素

方法二:分治算法(利用快排思想)

算法描述
  • 快排分为三个阶段:分解,解决,合并1( 分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]A[q+1..r],使得A[p..q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1..r]中的每个元素。)
  • 这里只用到分解。分解之后,我们可以知道比A[q]大的数字的个数,与k作比较:
    • 若个数大于k-1:则问题变为在A[q+1..r]中寻找第k大的元素
    • 若个数等于k-1:则第k大元素为A[q]
    • 若个数小于k-1:则问题变为在A[p..q-1]中寻找第k-r+q-1大的元素

参考代码

方法一:优先队列

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int,  vector<int>, greater<int> > queue;
        for (int i = 0; i < nums.size(); i++) {
            if (queue.size() < k)
                queue.push(nums[i]);
            else if (queue.top() < nums[i]) {
                queue.pop();
                queue.push(nums[i]);
            }
        }
        return queue.top();
    }
};

方法二:分治算法(利用快排思想)

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        if (nums.size() == 1) return nums[0];

        vector<int>::iterator pivot = nums.end() - 1;
        int i = -1, temp;
        for (auto j = nums.begin(); j != nums.end() - 1; j++)
            if (*j < *pivot) {
                i++;
                temp = nums[i];
                nums[i] = *j;
                *j = temp;
            }
        temp = nums[i + 1];
        nums[i + 1] = *pivot;
        *pivot = temp;
        if (nums.size() - i - 1 > k) {
            for (int p = 0; p <= i + 1; p++) {
                auto tmp = nums.begin();
                nums.erase(tmp);
            }
            return findKthLargest(nums, k);
        }
        else if (nums.size() - i - 1 == k) {
            return nums[i + 1];
        } else {
            int tmp = k - nums.size() + i + 1;
            while (nums.size() > i + 1)
                nums.pop_back();
            return findKthLargest(nums, tmp);
        }
    }
};

结语

事实上,方法二的代码并没有方法一的代码跑得快。我分析因为一方面的原因是递归是一种耗时的方法(建立新的函数栈,结束后销毁函数栈……);另一方面的原因是本来不需要对数组做删除元素的操作,只需要在递归的时候传递边界下标,但这道题目给定了参数列表,只能这么写了。


  1. 算法导论(原书第3版)/(美)科尔曼(Cormen, T.H.)等著;殷建平等译. —北京:机械工业出版社,2013.1,第95-97页
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值