algo/di-yi-zhan-da78c/shou-ba-sh-66994/kuai-su-pa-39aa2/ #1484
Replies: 7 comments 8 replies
-
尴尬了,使用快速选择排序, 提交 leetcode,居然没有我之前写的简易的二叉堆效率高,附上我写的简易二叉堆: class Solution {
public int findKthLargest(int[] nums, int k) {
if(k < 1 || k>nums.length) {
return -1;
}
return kthLargestByHeap(nums,k);
}
// 使用的是二叉堆
int kthLargestByHeap(int[] nums, int k) {
for (int i = nums.length >>> 1; i >= 0; i--) {
// heapify,建一个大顶堆
sink(nums, i, nums.length - 1);
}
int result = nums[0];
for (int i = 0; i < k; i++) {
int size = nums.length - 1 - i;
result = delMax(nums, size);
}
return result;
}
public int delMax(int[] arr, int size) {
int result = arr[0];
swap(arr, 0, size);
sink(arr, 0, size - 1);
return result;
}
// 大顶堆规则,最大元素在最上面
void sink(int[] arr, int k, int heapSize) {
int left = k * 2 + 1;
int right = left + 1;
while (left <= heapSize) {
int child = left;
if (right <= heapSize && arr[right] > arr[left]) {
child = right;
}
if (arr[k] >= arr[child]) {
break;
}
swap(arr, k, child);
k = child;
left = k * 2 + 1;
right = left + 1;
}
}
void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
} 快速选择排序执行时间就要要 2 s,而使用大顶堆的时间是 20 ms ,居然有 100 倍的性能差距 |
Beta Was this translation helpful? Give feedback.
-
按照文章的快速排序算法写了几遍,每次到边界点都弄不清。记得学数据结构的时候没这么复杂,翻出李春葆版的数据结构,交换数组元素那里写的更加简洁明了,这次终于写出来了。
|
Beta Was this translation helpful? Give feedback.
-
if (i >= j) {
break;
} 这里break时 swap(nums[lo], nums[j]); 会不会变成 |
Beta Was this translation helpful? Give feedback.
-
递归本来就是树形结构吧。 |
Beta Was this translation helpful? Give feedback.
-
文中的 partition 算法在力扣提交超时,下面的 partition 算法通过力扣测试,用时 5 ms class Solution {
public int findKthLargest(int[] nums, int k) {
k = nums.length - k;
int start = 0, end = nums.length - 1;
Random random = new Random();
while (start <= end) {
int pivot = start + random.nextInt(end - start + 1);
int[] equalRange = partition(nums, start, end, pivot);
if (k < equalRange[0]) end = equalRange[0] - 1;
else if (k > equalRange[1]) start = equalRange[1] + 1;
else return nums[equalRange[0]];
}
return Integer.MIN_VALUE;
}
/**
@param pivot 枢轴元素的索引
@return 长度为 2 的数组。另 a, b 表示返回数组的 0, 1 号元素,pivotValue 表示调用方法时的 nums[pivot],则方法返回后 nums 格局如下:
nums[start..a - 1] < pivotValue
nums[a..b] = pivotValue
nums[b + 1..end] > pivotValue
*/
int[] partition(int[] nums, int start, int end, int pivot) {
int pivotValue = nums[pivot];
// 循环常态:
// nums[start..i) < pivotValue
// nums[i..j) = pivotValue
// nums(k..end] > pivotValue
int i = start, j = i, k = end;
while (j <= k) {
if (nums[j] < pivotValue) {
if (i != j) swap(nums, i, j);
i++;
j++;
} else if (nums[j] == pivotValue) {
j++;
} else {
while (k > j && nums[k] > pivotValue) k--;
if (j < k) swap(nums, j, k);
k--;
}
}
return new int[] {i, j - 1};
}
void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
} |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
提一个建议哥, 我看您好多文章就有种感觉, 整体都写得很不错, 但是就是有些算法的边界条件没那么准确, 看起来感觉思路不那么清晰 static int partition(vector<int> &nums, int left, int right) {
// 以 nums[left] 为基准数
int i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left])
j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left])
i++; // 从左向右找首个大于基准数的元素
swap(nums[i], nums[j]); // 将基准数交换至两子数组的分界线
}
swap(nums[i], nums[left]); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
} 以上代码摘自其他教材 |
Beta Was this translation helpful? Give feedback.
-
algo/di-yi-zhan-da78c/shou-ba-sh-66994/kuai-su-pa-39aa2/
Info 数据结构精品课 (https://aep.h5.xeknow.com/s/1XJHEO) 和 递归算法专题课 (https://aep.xet.tech/s/3YGcq3) 限时附赠网站会员! 读完本文,你不仅学会了算法套路,还可以顺便解决如下题目: LeetCode 力扣 难度 :----: :----: :----: 215. Kth L...
https://labuladong.github.io/algo/di-yi-zhan-da78c/shou-ba-sh-66994/kuai-su-pa-39aa2/
Beta Was this translation helpful? Give feedback.
All reactions