LeetCode-215. 陣列中的第K個最大元素
阿新 • • 發佈:2018-12-11
題目
在未排序的陣列中找到第 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 ≤ 陣列的長度。
解題
- 方法一 : 任意一種O(nlogn)演算法對陣列進行降序排序, 取下標為k - 1的陣列元素即可
- 方法二 : 使用堆, 維護一個元素個數為k的最大堆, 將所有數字放入到最大堆中, 全部放完之後, 最大堆中最小的那個元素就是第k個最大的元素
- 方法三 : 快速排序思想, 使用三路快排, 每次都將陣列分割成三部分, 每次只需要在其中一部分繼續尋找, 時間複雜度O(logn), 方法三程式碼如下:
class Solution {
public int findKthLargest(int[] nums, int k) {
return partition(nums, 0, nums.length - 1, k);
}
// 在nums陣列[l...r]區間查詢第k個最大元素
// 使用三路快排的partition操作, 設定標定點為v, 等於v的部分就是這部分元素在陣列中應該待的位置
// 判斷k是否在等於v的部分,如果在的話, 就直接返回nums[k]即可
// 如果k在小於v的部分, 就在小於v的部分繼,否則就在大於v的部分繼續尋找
private int partition(int[] nums, int l, int r, int k){
int mid = l + (r - l) / 2;
swap(nums, l, mid);
int v = nums[l];
int left = l - 1; // 設定nums[l...left]區間的元素都大於v
int i = l; // 設定nums[left+1...i)區間的元素都等於v, i表示當前要考察的元素
int right = r + 1; // 設定[right...r]區間的元素都小於v
while(i < right){
if(nums[i] > v){
swap(nums, i, left + 1);
left++;
i++;
} else if (nums[i] == v){
i++;
} else { // nums[i] < v
swap(nums, i, right - 1);
right--;
}
}
if(k -1 <= left){
return partition(nums, l, left, k);
} else if (k - 1 >=right) {
return partition(nums, right, r, k);
} else { // left < k -1 < right , 表示第k個最大元素就在[left+1, right -1]這個區間中, 第k個最大元素已經處於它應該在的位置了,直接返回nums[k]即可
// 陣列下標從0開始,
return nums[k - 1];
}
}
private void swap(int nums[], int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}