215. Kth Largest Element in an Array 【leetcode解题报告】

题目:

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大(小)数。
1. 排序后取第k大,基于比较的排序最优O(lngn)
2.利用快速排序每次将数组分成两个part,与target进行比较,期望数据复杂度O(lgn),最差时间复杂度O(n^2)
3.使用最小堆或最大堆实现O(nlgn) ,可自己实现,也可以直接调用std::make_heap()
4.算法导论第九章,实现了期望及最差情况下为线性复杂度的O(n)算法:PART_SORT按5个一组,把n个数字分为n/5组,每组进行插入排序后,将每组的中位数再组成一个数组,递归调用PART_SORT找到其中位数mo。根据mo将原数组分成leftpart和rightpart。比较mo与target的值,来确定taret是在leftpart中还是rightpart中。继续递归,直到找到第k大的为止。

tips:

make_heap(_First, _Last, _Comp)
默认是建立最大堆的。对int类型,可以在第三个参数传入greater()得到最小堆。

这里暂时只对第二种方法进行实现。之所以写这篇博客,是发现,在快排时,适当优化povit的选择,会对显著提高算法速度…
优化前:
povit直接选择nums[right];
优化后:
povit选择nums[(right+left)/2];即选择中位数。

粗略分析可知,是很大程度上避免了nums为逆序列时造成的O(n^2)的情况!

leetcode提交结果:

快排povit取中位数 beats 98.72%    Accepted    10 ms   cpp
利用stl模板sort Kth Largest Element in an Array Accepted    12 ms   cpp
快排povit取最右端的数   Kth Largest Element in an Array Accepted    28 ms   cpp

代码:

class Solution {
public:


//     int findKthLargest(vector<int>& nums, int k) {

//         sort(nums.begin(),nums.end());
//         return nums[nums.size()-k];

//     }

    int findKthLargest(vector<int>& nums, int k) {
        int len = nums.size();
        int target = len-k; // 以0开始的数组,第k大=第len-k小

        //分治法求第k小的数
        int left = 0;
        int right = len-1;
        while(left<right){
            int p=partition(nums,left,right);
            if(p == target){
                return nums[p];
            }
            if(p<target){
                left = p+1;
            }else{
                right = p-1;
            }
        }
        return nums[left];
    }

    int partition(vector<int>& A,int left,int right){
        int mid = (left+right)/2;
        int key = A[mid];
        int temp = A[right];
        A[right]=A[mid];
        A[mid] =temp;
        while(left<right){
            while(left<right && A[left]<=key){
                ++left;
            }
            if(left<right){
                A[right--] = A[left];
            }
            while(left<right && A[right]>=key){
                --right;
            }
            if(left<right){
                A[left++] = A[right];
            }

        }
        A[left] = key;
        return left;

    }
};

猜你喜欢

转载自blog.csdn.net/tan_change/article/details/80139027