LeetCode題解 | 215. 陣列中的第K個最大元素
阿新 • • 發佈:2018-11-12
在未排序的陣列中找到第 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); }