分治

  1. 找第k小数的分治算法

可以使用“快速选择(Quickselect)”算法。其基本思想是:先从数组中选取一个基准元素pivot,然后将数组划分为小于pivot、等于pivot和大于pivot的三部分。

设小于pivot的元素个数为m:

如果k小于或等于m,说明第k小的数在小于pivot的部分中,继续在该部分递归查找。

如果k大于m且不超过“小于pivot的元素个数加上等于pivot的元素个数”,说明pivot就是第k小的数。

否则,第k小的数在大于pivot的部分中,继续在该部分查找第k-m-等于pivot元素个数小的数。

伪代码如下:

Select(A, k)
如果A中只有一个元素
返回A[0]

从A中选择一个元素作为pivot

L = A中所有小于pivot的元素
E = A中所有等于pivot的元素
R = A中所有大于pivot的元素

如果k <= L的长度
返回Select(L, k)

如果k <= L的长度 + E的长度
返回pivot

返回Select(R, k - L的长度 - E的长度)

  1. 时间复杂度分析

每次划分数组时,都需要遍历当前数组中的元素,因此一次划分操作的时间复杂度为O(n)。

最好情况下,每次选择的pivot都能将数组较均匀地划分为两部分。此时递推式为:

T(n) = T(n/2) + O(n)

因此,最好时间复杂度为O(n)。

最坏情况下,每次选择的pivot都是当前数组中的最小值或最大值。这样每次只能排除一个元素,递推式为:

T(n) = T(n-1) + O(n)

因此,最坏时间复杂度为O(n²)。

如果随机选择pivot,快速选择算法的期望时间复杂度通常为O(n)。

  1. 对分治法的体会和思考

分治法是一种把复杂问题逐步分解为规模更小、结构相似的子问题,再通过递归或合并得到原问题答案的算法思想。它的关键在于合理地划分问题,使每个子问题都比原问题更容易处理。

在找第k小数的问题中,不需要像排序算法那样把所有元素完全排序,只需要根据pivot的位置判断答案在哪一部分,并继续处理这一部分即可。这说明设计算法时,应尽量避免无关的计算,只保留解决问题所必需的信息。

同时,分治法的效率与划分是否均衡密切相关。若每次划分比较均匀,算法效率较高;若划分极不均匀,算法效率可能明显下降。因此,在实际应用中,选择合适的划分方法和基准元素十分重要。

通过学习分治法,我认识到,面对复杂问题时,可以先将问题拆分,再逐步解决各个部分。合理的分解不仅能降低问题难度,也能够提高算法效率。

posted @ 2026-10-13 18:39  难渡  阅读(5)  评论(0)    收藏  举报