1. 程式人生 > >[LeetCode] Kth Largest Element in an Array 陣列中第k大的數字

[LeetCode] Kth Largest Element in an Array 陣列中第k大的數字

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.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5

Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

這道題讓我們求陣列中第k大的數字,怎麼求呢,當然首先想到的是給陣列排序,然後求可以得到第k大的數字。先看一種利用c++的STL中的整合的排序方法,不用我們自己實現,這樣的話這道題只要兩行就完事了,程式碼如下:

解法一:

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

下面這種解法是利用了priority_queue的自動排序的特性,跟上面的解法思路上沒有什麼區別,當然我們也可以換成multiset來做,一個道理,參見程式碼如下:

解法二:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> q(nums.begin(), nums.end());
        for (int i = 0; i < k - 1; ++i) {
            q.pop();
        }
        return q.top();
    }
};

上面兩種方法雖然簡潔,但是確不是本題真正想考察的東西,可以說有一定的偷懶嫌疑。這道題最好的解法應該是下面這種做法,用到了快速排序Quick Sort的思想,這裡排序的方向是從小往大排。對快排不熟悉的童鞋們隨意上網搜些帖子看下吧,多如牛毛啊,總有一款適合你。核心思想是每次都要先找一箇中樞點Pivot,然後遍歷其他所有的數字,像這道題從小往大排的話,就把小於中樞點的數字放到左半邊,把大於中樞點的放在右半邊,這樣中樞點是整個陣列中第幾大的數字就確定了,雖然左右兩部分不一定是完全有序的,但是並不影響本題要求的結果,所以我們求出中樞點的位置,如果正好是k-1,那麼直接返回該位置上的數字;如果大於k-1,說明要求的數字在左半部分,更新右邊界,再求新的中樞點位置;反之則更新右半部分,求中樞點的位置;不得不說,這個思路真的是巧妙啊~

解法三:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int left = 0, right = nums.size() - 1;
        while (true) {
            int pos = partition(nums, left, right);
            if (pos == k - 1) return nums[pos];
            else if (pos > k - 1) right = pos - 1;
            else left = pos + 1;
        }
    }
    int partition(vector<int>& nums, int left, int right) {
        int pivot = nums[left], l = left + 1, r = right;
        while (l <= r) {
            if (nums[l] < pivot && nums[r] > pivot) {
                swap(nums[l++], nums[r--]);
            }
            if (nums[l] >= pivot) ++l;
            if (nums[r] <= pivot) --r;
        }
        swap(nums[left], nums[r]);
        return r;
    }
};

類似題目:

Kth Largest Element in a Stream

參考資料: