1. 程式人生 > >LeetCode題解 | 215. 陣列中的第K個最大元素

LeetCode題解 | 215. 陣列中的第K個最大元素

在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。

示例 1:

輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5

示例 2:

輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4  

說明:
你可以假設 k 總是有效的,且 1 ≤ k ≤ 陣列的長度。

大家看到這道題很高興的呼叫了sort(),也有手搓快排的那麼時間複雜度都在O(nlgn)
我們仔細想想快排的思想 本質上是在劃分 那麼我們先愉快的寫一個劃分吧
注意這裡要從大到小了

int partition(vector<int>& nums, int l,int r){
        int temp = nums[l];
        while(l < r){
            int temp = nums[l];
            while(l < r){
                while(l < r && nums[r] <= temp) r--;
                swap(nums[l],nums[r]);
                while(l < r && nums[l] >= temp) l++;
                swap(nums[l],nums[r]);
            }
        }
        nums[l] = temp;
        return l;
    }

這裡我們執行了一次劃分操作,即把基準temp放在了一個位置,基準前的都比基準大,基準後的都比基準小 l就是基準最後所在的位置
那麼這是想一想 如果l剛好和k-1相等(假設陣列下標從0開始) 那麼基準不就是要找的數字嗎(前面有k-1個比他大的 他就是第k大的) 我們就可以愉快的返回了;如果 l > k-1那麼很不幸運,我們的基準選的有點小了 造成基準是第k+eps(eps=1、2...)個大的元素,那麼我們就在[left,l-1]這個區間找找;反正,基準選大了,就在[l+1,right]裡面找找

int search(vector<int>& nums,int l,int r,int k){
        int m =partition(nums,l,r);
        if(m == k-1) return nums[m];
        else if(m > k-1) return search(nums,l,m-1,k);
        else return search(nums,m+1,r,k);
    }

這樣就解決了問題。
我們並沒有對陣列進行排序,而是根據情況遞迴的尋找第k大的數,因此複雜度是比快排本身要低的,為O(n)。
但是如果陣列本身就是有序的情況下,複雜度還是會飆升至O(n^2 )
關於這個問題的詳細複雜度分析可以看看算導的第九章

完整函式程式碼 想嘗試的可以移步leetcode
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/description/

int partition(vector<int>& nums, int l,int r){
        int temp = nums[l];
        while(l < r){
            int temp = nums[l];
            while(l < r){
                while(l < r && nums[r] <= temp) r--;
                swap(nums[l],nums[r]);
                while(l < r && nums[l] >= temp) l++;
                swap(nums[l],nums[r]);
            }
        }
        nums[l] = temp;
        return l;
}

int search(vector<int>& nums,int l,int r,int k){
        int m =partition(nums,l,r);
        if(m == k-1) return nums[m];
        else if(m > k-1) return search(nums,l,m-1,k);
        else return search(nums,m+1,r,k);
}

int findKthLargest(vector<int>& nums, int k) {
        int length = nums.size();
        if(k > length) return 0;
        else return search(nums,0,length-1,k);
}