1、描述找第k小的数的分治算法
1.1、问题描述
给定长度为n的无序数组,找出其中第k小的数
1.2、算法思路
该问题可以依照快排算法的划分算法来进行求解,即分治思想:
- 通过选定数组中一个元素作为基准点(pivot),将数组划分为两部,使得:左半部所有数比基准点小 ,右半部比基准点大。划分后的数组不会确保所有数都在其最终位置,但肯定的是,基准元素是在其最终位置上的。
- 在划分后,返回该基准点的下标,如果等于 k-1(即第k的元素的下标),则找到了该数,可直接返回。否则,若大于,将范围缩小至左半边,小于则缩小至右半端,并进行重复查找。
1.3、具体思路
此处使用自然语言进行描述,因为写出的伪代码与实际代码无异
划分:
- 将数组子序列 left ~ right 中第一个值选为基准值
- 通过把左右指针逐步向中间靠拢:小于pivot的元素移动至右方,大于pivot的元素移动至左方
- 在左右指针重合后返回pivot的下标
查找:
- 通过划分函数确定一个元素的位置:若等于 k-1,直接返回,否则循环查找:
- 如果pivot的值大于 k-1,只需往左方查找
- 如果pivot的值小于 k-1,只需往右方查找
2、算法的时间复杂度
递归关系式:T(n) = T(n/2) + O(n)
2.1、最好时间复杂度
当每次选择的基准点都能正好将数组均分时,算法的时间复杂度为O(n),因为每次划分都会将问题规模减半,递归深度为O(logn)
2.2、最坏时间复杂度
如果每次选择的基准元素是极端值,导致每次只能减少一个元素,此时的时间复杂度为O(n²)
3、心得
分治法的核心在于“分而治之”,它将一个复杂问题拆分为若干规模较小且独立的子问题,通过递归的方式逐个解决这些子问题,最后再将子问题的解组合成原问题的解。其巧妙的点在于,将原问题的复杂度转移到了多个小的问题上,让求解过程更加简单和高效。当然,在一些情况下,在规划和设计不合理的情况下,分治法也不一定比其他方法来得高效。