【每日一題】LeetCode. 215. 數組中的第K個最大元素

每日一題,防止癡呆 = =

一、題目大意

在未排序的數組中找到第 k 個最大的元素。請注意,你需要找的是數組排序後的第 k 個最大的元素,而不是第 k 個不同的元素。
在這裏插入圖片描述
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array

二、題目思路以及AC代碼

思路一:快速排序

首先的第一個思路就是直接全部排序,然後返回下標爲 size - k 的元素即可,這樣的時間複雜度是O(NlogN),空間複雜度爲O(1).

思路二:快速選擇

另一個思路就是在快速排序的基礎上去修改,從而得到快速選擇算法,其思想是這樣的。在快速排序的過程中,我們每次需要選擇一個基準元素,然後確定這個基準元素的位置,使得其左邊的元素都小於等於它,它右邊的元素都大於等於它,然後再對兩側的子數組進行遞歸排序。

因爲這裏我們只需要找到排序後數組第 size - k 位置處的元素,所以我們大可不必要對所有數都進行排序,因爲我們在第一次選擇一個基準元素找到其位置後,可以判斷我們要找的元素在其左側還是右側,假設在其右側,那麼我們只需要對右側的數組進行排序就可以了,不需要對左側的數組也進行排序,這樣就可以優化時間複雜度。

但是我們知道如果基準元素選擇的不好,遇到最差的情況時間複雜度也會達到O(N2)的,所以這裏採用每次隨機選擇基準元素的方法,從而使期望的時間複雜度爲O(N)。

AC代碼

快速排序:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int n_size = nums.size();
        sort(nums.begin(), nums.end());

        return nums[n_size - k];
    }
};

快速選擇:

class Solution {
public:
    int quick_selection(vector<int>& nums, int l, int r, int index) {
        int q = random_partition(nums, l, r);
        if (q == index) return nums[q];
        else if (q < index) return quick_selection(nums, q + 1, r, index);
        else return quick_selection(nums, l, q - 1, index);
    }

    int random_partition(vector<int>& nums, int l, int r) {
        int i = rand() % (r - l + 1) + l;
        swap(nums[i], nums[r]);
        return partition(nums, l, r);
    }

    int partition(vector<int>& nums, int l, int r) {
        int target = nums[r];
        int i = l;
        for (int j=l;j<r;j++) {
            if (nums[j] <= target) {
                swap(nums[i++], nums[j]);
            }
        }
        swap(nums[i], nums[r]);
        return i;
    }

    int findKthLargest(vector<int>& nums, int k) {
        srand(time(0));
        return quick_selection(nums, 0, nums.size() - 1, nums.size() - k);
    }
};

如果有問題,歡迎大家指正!!!

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