[LeetCode 215]Kth Largest Element in an Array (分治法/快速排序)

来源:互联网 发布:双色球旋转矩阵出6保6 编辑:程序博客网 时间:2024/05/29 19:13

215. Kth Largest Element in an Array

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.


朴素的算法是先对数组排序,然后取第k个数,此即为第k大数,此时复杂度为O(nlogn)
但是可以想见,排序其实额外做了一些工作,所以复杂度还有优化的余地。

先来想一想快速排序是怎么做的。首先取一个主值pivot,然后以该值为界,将数组分为大于pivot与小于pivot两部分,然后分别对这两部分递归的排序,以此得到一个良序的序列。反观我们的问题,这是求解一个局部的解,并不需要全局良序,所以当我们将数组分为两部分后,虽然还不知道确切的值,但可以确定我们要求的解位于哪一个部分,然后只求解这一部分就可以了。

平均来说,每次递归将问题规模减半。假设第一层递归的复杂度为1,那么第二层平均来说会是1/2,第三层1/4以此类推。最后求和1+1/2+1/4+…=2,所以总体复杂度为O(n)

PS:有样例卡每次将nums[0]作为pivot的情况,所以建议另找一值作为pivot


代码如下:

#include <algorithm>class Solution {public:    int findKthLargest(vector<int>& nums, int k) {        int n = nums.size();        return recFind(nums, k, 0, n);    }    int recFind(vector<int> &nums, int k, int lo, int hi) {        swap(nums[lo], nums[lo+(hi-lo)/2]);        int pivot = nums[lo];        int i = lo, j = hi-1;        while (i != j) {            while (j > i && nums[j] > pivot) j--;            swap(nums[i], nums[j]);            while (i < j && nums[i] <= pivot) i++;            swap(nums[i], nums[j]);        }        int right_size = hi-i;        if (right_size == k) return nums[i];        if (right_size > k) return  recFind(nums, k, i, hi);        return recFind(nums, k-right_size, lo, i);    }};
0 0
原创粉丝点击