215. 数组中的第K个最大元素

215. 数组中的第K个最大元素

leetcode 215. 数组中的第K个最大元素


题目: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 ≤ 数组的长度。

方法一:java.util.Arrays的sort方法

思路:使用java.util.Arrays的sort方法排序

运行数据:执行用时:2 ms,内存消耗:40.4 MB

1
2
3
4
5
// LeetCode指定调用方法
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}

方法二:堆排序(大顶堆)

思路:使用堆排序(大顶堆)

运行数据:执行用时:2 ms,内存消耗:39.9 MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// LeetCode指定调用方法
public int findKthLargest(int[] nums, int k) {
int len = nums.length;
createBigHeap(nums, len);

// 通过大顶堆排序,找出第 k个最大的元素
for (int i = 1; i <= k; i++) {
int temp = nums[len - i];
nums[len - i] = nums[0];
nums[0] = temp;
adjustBigHeap(nums, 0, len - i);
}

return nums[len - k];
}

// 创建大顶堆
public void createBigHeap(int[] nums, int len) {
for (int i = len / 2 - 1; i >= 0; i--) {
//从第一个非叶子结点从下至上,从右至左调整结构
adjustBigHeap(nums, i, len);
}
}

// 调整大顶堆
public void adjustBigHeap(int[] nums, int i, int len) {
int temp = nums[i];
for(int j = i * 2 + 1; j < len; j = j * 2 + 1){ // 遍历从i开始的左子节点,左子节点的左子节点
if(j + 1 < len && nums[j] < nums[j + 1]){ // 如果左子结点小于右子结点,则将子节点指针j指向右子结点
j++;
}
if(nums[j] > temp){ // 如果子节点大于父节点,将子节点值赋给父节点,并将父节点指针i指向该子节点
nums[i] = nums[j];
i = j;
}else{
break;
}
}
nums[i] = temp;
}

方法三:快速排序(快速选择)

思路:使用快速排序,并结合题目要求对其进行优化。(通过随机数确定枢轴,降低有序数据对快速排序的影响,当确定了第 k个最大的元素时,结束快速排序,直接返回结果)

运行数据:执行用时:2 ms,内存消耗:39.9 MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// LeetCode指定调用方法
public int findKthLargest(int[] nums, int k) {

int len = nums.length;
int low = 0;
int high = len - 1;

// 将第 k个最大的元素的下标赋值给k(从小到大排序)
k = len - k;
// 枢轴位置
int pos;

// 结合题目需求,优化后的快速排序
while (low < high) {
pos = partition(nums, low, high);
if (pos == k) {
break;
} else if (pos > k) {
high = pos - 1;
} else {
low = pos + 1;
}
}
return nums[k];
}

// 进行一次快速排序,确定枢轴位置
public int partition(int[] nums, int low, int high) {

// 通过随机数确定枢轴,降低有序数据对快速排序的影响
Random random = new Random();
int random_index = low + random.nextInt(high - low);
// 枢轴
int temp = nums[random_index];
nums[random_index] = nums[low];
nums[low] = temp;
while (low < high) {
while (low < high && nums[high] >= temp) { // 从右往左找小于枢轴的元素
high--;
}
nums[low] = nums[high];
while (low < high && nums[low] <= temp) { // 从左往右找大于枢轴的元素
low++;
}
nums[high] = nums[low];
}
nums[low] = temp;
return low; // 返回枢轴位置
}

学习所得,资料、图片部分来源于网络,如有侵权,请联系本人删除。

才疏学浅,若有错误或不当之处,可批评指正,还请见谅!


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×