1.#include
using namespace std;
int partition(int a[], int left, int right) {
int pivot = a[left];
int i = left, j = right;
while (i < j) {
while (i < j && a[j] >= pivot) j--;
a[i] = a[j];
while (i < j && a[i] <= pivot) i++;
a[j] = a[i];
}
a[i] = pivot;
return i;
}
int find(int a[], int left, int right, int k) {
int p = partition(a, left, right);
if (p + 1 == k) return a[p];
if (p + 1 > k) return find(a, left, p - 1, k);
else return find(a, p + 1, right, k);
}
int main() {
int n, k;
cin >> n >> k;
int a[10000];
for (int i = 0; i < n; i++) cin >> a[i];
cout << find(a, 0, n - 1, k) << endl;
return 0;
}
对于这段代码进行解释的话,首先创建一个partition函数,声明一个pivot基准数(数组最左边的数),声明最左最右两个指针用来和基准数进行比较,小于基准数的统统放左边,大于它的放右边,随后返回基准数所在的排位;随后创建一个find函数,声明p用来记录基准数所在排位,与目标排位k进行比较,若正好等于k,返回其值,若大于k则去基准数的左边进行递归寻找,若小于k则去基准数的右边进行寻找,返回其值;最后只需按照需求输入n,k,再使用find函数,即可找到第k小的数。
2.最好时间复杂度为O(n)
最坏时间复杂度为O(n方)
3.通过本章的学习我认为分治法的价值在于其 “拆解 - 求解 - 整合” 的逻辑闭环,它通过降低问题规模提升效率,通过递归简化实现难度,但也受限于拆分策略与合并成本。学习分治法不仅是掌握一种算法技巧,更重要的是培养 “化繁为简” 的思维:面对复杂问题时,先思考 “如何拆分”“如何合并”,再结合问题特性优化细节。例如,在大规模数据处理中,分治法的思想延伸为 “分而治之” 的分布式计算(如 MapReduce):将数据拆分到多个节点并行处理,再汇总结果;快速选择算法中,通过partition操作将 “找第 k 小元素” 分解为 “在左半部分找” 或 “在右半部分找”,本质是用划分缩小问题规模,且无需合并子问题(因每次划分已直接定位目标范围);而归并排序则更完整地体现了三步曲:分解为两个子数组,递归排序子数组,最后合并两个有序子数组得到原数组的排序结果。