算法設計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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章