[Leetcode] 215. Kth Largest Element in an Array 解题报告

来源:互联网 发布:淘宝app抢购需要刷新吗 编辑:程序博客网 时间:2024/05/21 06:58

题目

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.

思路

1、基于堆排序的方法:联想到堆排序的实现,我们可以在这里采用:首先将数组调整成为一个大顶推,然后依次往外取元素,取到的第k个元素即为第k大的。建堆的时间复杂度是O(n),每次pop_heap之后调整堆的时间复杂度是O(logn),所以总体时间复杂度是O(n+klogn),空间复杂度是O(1)(如果允许修改原数组的话,否则空间复杂度是O(n))。

2、基于快速排序的方法:在快速排序中有一个子函数叫做partition,负责将某个哨兵元素排到相应的位置,左边的位置上的值都比它小,而右边位置上的值都比它大。这个方法的理论复杂度是O(n)。具体到这道题目,我们使用分治每次将数组划分为两段,并且返回划分点的位置,如果这个位置恰好是我们要的第k大的数,那么返回这个数即可。否则如果返回的位置小于要找的位置,则向右边的一半数组继续寻找;如果返回的位置大于要找的位置,则向左边继续寻找。这种方法的空间复杂度是O(1),平均时间复杂度是O(nlogn),最大时间复杂度是O(n^2)。但是通常情况下,基于快速排序的方法的实际花费时间要小于理论值(和现代计算机体系结构有关)。

代码

1、基于堆排序的方法:

class Solution {public:    int findKthLargest(vector<int>& nums, int k) {        make_heap(nums.begin(), nums.end());        for(int i = 0; i < k - 1; ++i) {            std::pop_heap(nums.begin(), nums.end());            nums.pop_back();        }        return nums.front();    }};

2、基于快速排序的方法:

class Solution {public:    int findKthLargest(vector<int>& nums, int k) {          int len = nums.size(), left = 0, right = len-1, ans, pos = len-k;          while((ans=partition(nums, left, right)) != pos) {             ans<pos?left = ans + 1: right = ans - 1;          }        return nums[len-k];      }  private:    int partition(vector<int>& nums, int left, int right) {          int val = nums[right];          for(int i = left; i < right; ++i) {              if(nums[i] < val) {                swap(nums[left++], nums[i]);              }        }        swap(nums[right], nums[left]);          return left;      }  };