434
社区成员
发帖
与我相关
我的任务
分享在快速排序算法中,我们选择一个枢轴来对数组进行分区,确保枢轴左侧的所有元素都小于枢轴,而右侧的所有元素都大于枢轴。基于此,我们可以通过在每次分区步骤中检查枢轴的索引是否等于 k 来找到第 k 个最小元素。
cpp
int partition(int arr[], int low, int high) { // 执行与快速排序相同的分区操作
int pivot = arr[low]; // pivot 表示枢轴元素
int i = high + 1;
for (int j = high; j > low; j--) {
if (arr[j] > pivot) {
i--;
swap(arr[i], arr[j]);
}
}
swap(arr[i - 1], arr[low]);
return i - 1;
}
int qsort(int arr[], int low, int high, int k) { // 快速排序算法变体
if (low <= high) {
int pi = partition(arr, low, high);
if (pi == k) {
return arr[pi]; // 找到第 k 个最小元素
}
if (pi > k) {
return qsort(arr, low, pi - 1, k); // 在左侧分区中继续查找
}
else {
return qsort(arr, pi + 1, high, k); // 在右侧分区中继续查找
}
} return -1; // 未找到
}
在这段代码中,添加了一个条件来检查 pi 是否等于 k。如果 pi == k,则说明当前的分区点就是第 k 个最小元素。如果 pi > k,我们在范围 (low, pi - 1) 中继续查找;如果 pi < k,我们将在范围 (pi + 1, high) 中查找。因此,我们不需要执行完整的快速排序。
在最坏情况下,该算法的表现与快速排序算法的最坏情况相似,其中每次递归只排序一个元素。第一次分区需要 O(n) 时间,第二次 O(n-1),依此类推,结果为:
T(n)=n+(n−1)+(n−2)+...+1=n(n+1)2=O(n2)。T(n)=n+(n−1)+(n−2)+...+1=2n(n+1)=O(n2)。
在最佳情况下,我们只需一步分区就可以找到第 k 个元素,时间复杂度为 O(n)。
分治法将复杂的问题转化为多个较小的相似子问题,并逐一解决它们,以获得原问题的解。这种将复杂问题简化为简单问题的思想在我们日常生活中也很重要。