算法设计Week2 LeetCode Algorithms Problem #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.


解法一:

使用C++中提供的函数nth_element,直接找出所求元素,时间复杂度为O(n)。最后用时很短,仅需9ms。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        nth_element(nums.begin(), nums.end() - k, nums.end());
        return nums[nums.size() - k];
    }
};

解法二(使用分治算法):

根据书上的随机分治算法,首先从数组中随机选取一个元素v,重新安排数组,把比v大的元素放到数组左边,比v小的数放在数组右边,v的存储位置m就说明v是数组中第m+1大的元素。如果m+1=k,说明v刚好是我们要找的元素;如果m+1< k,说明要找的元素在数组的右半段;反之,要找的元素在数组的左半段。算法如下图所示,图中 SL 表示重排后数组的左半边, Sv 表示数组中等于v的部分, SR 表示数组的右半边。
分治算法

算法中还有一点需要考虑:选择v后,如何将数组重排?实际上,可以先把目标元素存到数组末尾,然后遍历数组,同时维护一个storeidx(初值为0),如果遇到比目标元素大的元素,则与storeidx所代表的元素进行交换,然后将storeidx的值增加1,遍历完成后storeidx的值就应该是目标元素最后需要存放的数组下标。这样的话这一部分的空间复杂度仅为O(1)。
整体代码如下:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        return selection(nums,0,nums.size() - 1,k);
    }

    int selection(vector<int>& nums, int left, int right, int k){
        int random, storeidx, nums_rand;
        int length = right - left + 1;

        // pick a random element in array
        srand(time(NULL));
        random = rand() % length + left;
        nums_rand = nums[random];

        // put the elements larger than nums_rand to left, others to right
        swap(nums[random],nums[right]);
        storeidx = left;
        for(int i = left;i < right;i++){
            if(nums[i] > nums_rand){
                swap(nums[storeidx], nums[i]);
                storeidx++;
            }
        }
        swap(nums[storeidx], nums[right]);

        // find the kth largest number
        if((storeidx - left + 1) == k) return nums_rand;
        else if((storeidx - left + 1) > k) return selection(nums,left,storeidx - 1,k);
        else return selection(nums, storeidx + 1, right, k - (storeidx - left + 1));
    }

    void swap(int &a,int &b){
        int temp = a;
        a = b;
        b = temp;
    }
};

该算法的思路其实和快排一致,运行速度也很快,最后运行时间为9ms。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值