
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。
未排序数组中第 k 个最小/最大元素 预期线性时间(K’th Smallest/Largest Element in Unsorted Array | Expected Linear Time)
给定一个由不同整数组成的数组和一个整数 k,其中 k 小于数组的大小,任务是找到数组中第k小的元素。
例如:
输入: arr = [7, 10, 4, 3, 20, 15], k = 3
输出: 7
解释:排序后的数组为 [3, 4, 7, 10, 15, 20],因此第三小的元素是 7。
输入: arr = [7, 10, 4, 3, 20, 15], k = 4
输出: 10
解释:排序后的数组为 [3, 4, 7, 10, 15, 20],因此第 4 小的元素是 10。
请注意,解决“无序数组中最小/最大元素”问题有多种方法。本文讨论的方案在实践中效果最佳。
无序数组中最小/最大元素:
C++ 第k个最小元素 C++ 第k个最小元素(K’th Smallest Element)-CSDN博客
C# 第k个最小元素 C# 第k个最小元素(K’th Smallest Element)-CSDN博客
Java 第k个最小元素 Java 第k个最小元素(K’th Smallest Element)-CSDN博客
Python 第k个最小元素 https://blog.csdn.net/hefeng_aspnet/article/details/163051049
JavaScript 第k个最小元素 https://blog.csdn.net/hefeng_aspnet/article/details/163051180
其思路是使用随机枢轴选择来划分数组,通过专注于第 k 个元素所在的子数组来缩小搜索空间。
循序渐进的方法
随机选择枢轴元素:随机选择一个元素作为枢轴元素。这有助于避免某些情况下的最坏情况(例如数组已排序时)。
分区:重新排列数组,使所有小于枢轴元素的元素位于左侧,所有大于枢轴元素的元素位于右侧。
递归搜索:枢轴元素确定位置后,如果其索引与第 n 次比较相等,则它是第 K 个大元素。否则,根据与第 n 次-k 比较的结果,递归地在相应的分区(左侧或右侧)中搜索-k。
// JavaScript program to find K’th Smallest/
// Largest Element in Unsorted Array
// Partition function: Rearranges elements
// around a pivot (last element)
function partition(arr, l, r) {
let x = arr[r];
let i = l;
// Iterate through the subarray
for (let j = l; j <= r - 1; j++) {
// Move elements <= pivot to the left partition
if (arr[j] <= x) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}
// Place the pivot in its correct position
[arr[i], arr[r]] = [arr[r], arr[i]];
return i;
}
// Randomizes the pivot to avoid worst-case performance
function randomPartition(arr, l, r) {
let n = r - l + 1;
let pivot = Math.floor(Math.random() * n);
[arr[l + pivot], arr[r]] = [arr[r], arr[l + pivot]];
return partition(arr, l, r);
}
// function to find the k'th smallest element using QuickSelect
function quickSelect(arr, l, r, k) {
// Check if k is within the valid range of the current subarray
if (k > 0 && k <= r - l + 1) {
// Partition the array and get the pivot's final position
let pos = randomPartition(arr, l, r);
// If pivot is the k'th element, return it
if (pos - l == k - 1)
return arr[pos];
// If pivot's position is larger than k, search left subarray
if (pos - l > k - 1)
return quickSelect(arr, l, pos - 1, k);
// Otherwise, search right subarray and adjust k
// (k is reduced by the size of the left partition)
return quickSelect(arr, pos + 1, r, k - (pos - l + 1));
}
// Return Infinity for invalid k (error handling)
return Infinity;
}
function kthSmallest(arr, k) {
let n = arr.length;
return quickSelect(arr, 0, n - 1, k);
}
let arr = [12, 3, 5, 7, 4, 19, 26];
let k = 3;
console.log(kthSmallest(arr, k));
输出
5
时间复杂度:O(n)。上述解决方案的最坏情况时间复杂度仍然是 O(n² )。在最坏情况下,随机函数可能总是选择一个角点元素。然而,平均情况时间复杂度为 O(n²) O(n)。分析中的假设是,随机数生成器生成输入范围内任意数字的概率均等。
辅助空间:O(1),因为使用了常量变量。
即使最坏情况下的时间复杂度是二次方的,但这种解决方案在实践中效果最佳。
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

372

被折叠的 条评论
为什么被折叠?



