1.请用自然语言或伪代码描述找第k小的数的分治算法:
代码:
include
// 划分函数,根据a[left]对a[left..right]进行划分
int partition(int a[], int left, int right) {
int pivot = a[left]; // 选择第一个元素作为基准
int i = left, j = right;
while (i < j) {// 从右向左找第一个小于pivot的元素while (i < j && a[j] >= pivot) {j--;}if (i < j) {a[i] = a[j];i++;}// 从左向右找第一个大于pivot的元素while (i < j && a[i] <= pivot) {i++;}if (i < j) {a[j] = a[i];j--;}
}a[i] = pivot; // 基准元素归位
return i; // 返回基准元素的位置
}
// 查找第k小元素的函数
int find(int a[], int left, int right, int k) {
if (left == right) {
return a[left];
}
int pos = partition(a, left, right);// 计算当前基准元素是第几小的元素(在[left,right]范围内的排名)
int currentK = pos - left + 1;if (currentK == k) {// 正好找到第k小的元素return a[pos];
} else if (currentK > k) {// 第k小的元素在左半部分return find(a, left, pos - 1, k);
} else {// 第k小的元素在右半部分return find(a, pos + 1, right, k - currentK);
}
}
int main() {
int n, k;
std::cin >> n >> k;
int* a = new int[n];
for (int i = 0; i < n; i++) {std::cin >> a[i];
}int result = find(a, 0, n - 1, k);
std::cout << result << std::endl;delete[] a;
return 0;
}
自然语言解释:
这段代码的函数find用来找left和right之间的第k小的数,所以传入参数为数组,k,left和right。在find函数中首先规定了边界条件,即当猜的数所在的数组只有一个元素的时候,返回这个元素。如果不符合边界条件的话,通过partition函数将left位置的元素作为基准元素,找到数组中比基准元素大的元素和数组中比基准元素小的元素,大的放在右边,小的放在左边,然后partition函数返回一个基准元素的下标,再通过简单的计算得到这个下标是left和right中第几小的元素,并与k进行对比,如果和k相等,说明找到了第k小的元素,返回数组中的对应值即可,如果比k小,不满足条件,说明第k小的元素在基准元素的右半部分,然后递归调用函数find在基准元素+1位置开始到right再进行一次上述过程,k也由k变成k-current,说明整个数组中第k小的元素是基准元素的右半部分中的第k-current小的元素;如果比k大,说明第k小的元素在基准元素的左半部分,故递归调用find函数在left和基准元素前一个元素间寻找第k小的元素。
2.分析该算法的最好时间复杂度和最坏时间复杂度:
这个算法的最好情况应该是第一个元素就是我们要找的第k小的元素,但是我们还要再partition函数中把比基准元素小的元素放在左边,把比基准元素大的元素放在基准元素的右边,总共有n个元素。所以复杂度应该是O(n)
最坏情况就是每次我们选择的基准元素的情况都很极端,都是最小的或者是最大的,这样的话我们每次都要进行n次对数组(数组总共有n个元素)位置的重整,所有最坏情况的复杂度是O(n*n)
3.结合本章的学习,谈谈你对分治法的体会和思考
分治法本质上是一种降低问题复杂程度的方法,当你面对一个看起来无从下手的问题的时候,可以考虑将这个问题先分解为几个更加简单的子问题,先解决这些更为简单的子问题,在将子问题链接起来就可以获得原问题的答案,而子问题一直分解下去就能分解到你能解决的情况。所以我们要先解决子问题,如果连子问题都解决不了,那就相当于递归没有边界条件,就无法利用递归的想法来解决这个问题。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/953721.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!