【LeetCodeゼロブラシから】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
Note: You may assume k is always valid, 1 ≤ k ≤ array's length.
回答:
この問題「プログラミングの美しさ」には詳細な検討がある.最も速い方法はクイックソート(Quick Sorting)のように、keyより大きい部分とkeyより小さい部分を毎回区別することです.
keyより小さい個数がKより大きい場合、keyより大きい部分は検索されません.keyより小さい個数がKより小さい場合、keyより大きい個数のうち(K−Kより小さい個数)より大きい数を探す.
このようにして、毎回の約半分の数字を探す必要がなく、時間の複雑さは約O(n+n/2+n/4+..+1)=O(2 n)=O(n)である.
最後に、高速ソート、二分ソートのように、二分(再帰)のサブ問題では中間要素を除去すべきである(範囲を縮小するたびに、範囲が変わらない死のサイクルを防ぐ).
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. Note: You may assume k is always valid, 1 ≤ k ≤ array's length.
回答:
この問題「プログラミングの美しさ」には詳細な検討がある.最も速い方法はクイックソート(Quick Sorting)のように、keyより大きい部分とkeyより小さい部分を毎回区別することです.
keyより小さい個数がKより大きい場合、keyより大きい部分は検索されません.keyより小さい個数がKより小さい場合、keyより大きい個数のうち(K−Kより小さい個数)より大きい数を探す.
このようにして、毎回の約半分の数字を探す必要がなく、時間の複雑さは約O(n+n/2+n/4+..+1)=O(2 n)=O(n)である.
最後に、高速ソート、二分ソートのように、二分(再帰)のサブ問題では中間要素を除去すべきである(範囲を縮小するたびに、範囲が変わらない死のサイクルを防ぐ).
class Solution {
public:
void swap(int& a, int&b) {
int tmp = a;
a = b;
b = tmp;
}
int findKthLargest(vector<int>& nums, int k) {
int head = 0;
int tail = nums.size() - 1;
int index = 0;
while(head < tail) {
while(nums[tail] <= nums[index] && head < tail) tail--;
swap(nums[tail], nums[index]);
index = tail;
while(nums[head] >= nums[index] && head < tail) head++;
swap(nums[head], nums[index]);
index = head;
}
if(k == index + 1) return nums[index];
else if(k < index + 1) {
vector<int> sub(nums.begin(), nums.begin() + index);
return findKthLargest(sub, k);
}
else if(k > index + 1) {
vector<int> sub(nums.begin() + index + 1, nums.end());
return findKthLargest(sub, k - index - 1);
}
}
};