題目描述
在未排序的數組中找到第 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 ≤ 數組的長度。
題解
根據問題的描述其實我們很容易想到先排序再取第k個值, 這種方式也就是我們俗稱的暴力求解法。
暴力求解法
思路分析:
數組排序后的第k個最大元素,舉例說明一下:
數組一共有5個元素時,找第2大,索引值是3;找第4大,索引值是1;根據這個邏輯我們可以推導出,數組升序排序以后,結果元素的索引值是數組長度減去k的值。
代碼示例:
public static int findKthLargest(int[] nums, int k) {
int len = nums.length;
Arrays.sort(nums);
return nums[len - k];
}
復雜度分析:
- 時間復雜度:O(N log N), 這里直接使用Arrays.sort(nums);將數據排序,大家都知道jdk默認使用的是快速排序,快速排序的平均時間復雜度是O(N log N)。
- 空間復雜度:O(1),因為是原地排序,沒有用到外部輔助空間。
暴力求解法(升級版)
思路分析:
根據暴力求解法中用的快排思路,其實我可以對快排做近一步升級,首先我們隨機選擇一個元素,並在線性時間內找到其對應在數組中的位置,這樣數組就被分成了兩部分,一部分是小於元素值的部分,一部分是大於元素值的部分,這時我們在比較這個元素與k的大小來決定我們在那一部分數組繼續做快速排序。這種思路其實就是快速排序中partition(切分)的操作。
每次partition操作總能排定一個元素,還能夠知道這個元素它在數組中的最終位置,然后我們在根據partition后的結果來減少范圍,這樣的思想叫做“減而治之”。
代碼示例:
public static int findKthLargest(int[] nums, int k) {
int leng = nums.length;
int left = 0;
int right = leng - 1;
int target = leng - k;
return quickSelect(nums, left, right, target);
}
/**
* 排序
* @param nums
* @param left
* @param right
* @param target
* @return
*/
public static int quickSelect(int[] nums, int left, int right, int target) {
if (left == right) {
return nums[left];
}
//隨機選擇一個
Random random = new Random();
int pivot = left + random.nextInt(right - left);
pivot = partition(nums, left, right, pivot);
if (target == pivot) {
return nums[target];
}
if (target < pivot) {
return quickSelect(nums, left, pivot - 1, target);
}
return quickSelect(nums, pivot + 1, right, target);
}
/**
* partition切分
* @param nums
* @param left
* @param right
* @param target
* @return
*/
private static int partition(int[] nums, int left, int right, int target) {
int pivot = nums[target];
swap(nums, target, right);
int j = left;
for (int i = left; i <= right; i++) {
if (nums[i] < pivot) {
swap(nums, j, i);
j++;
}
}
swap(nums, j, right);
return j;
}
/**
* 交換
* @param nums
* @param a
* @param b
*/
public static void swap(int[] nums, int a, int b) {
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
復雜度分析:
- 時間復雜度:平均情況O(N), 最壞情況O($N^2$).
- 空間復雜度:O(1).
- 寫作不易,轉載請注明出處,喜歡的小伙伴可以關注公眾號查看更多喜歡的文章。
- 聯系方式:4272231@163.com
- QQ:95472323
- 微信:ffj2000