第二章作业
函数 quickSelect(arr, left, right, k):
如果 left == right:
返回 arr[left] // 只有一个元素,就是它
// 分区过程
pivot_index = partition(arr, left, right)
// 判断主元位置与k的关系
如果 k-1 == pivot_index:
返回 arr[pivot_index]
否则 如果 k-1 < pivot_index:
返回 quickSelect(arr, left, pivot_index - 1, k)
否则:
返回 quickSelect(arr, pivot_index + 1, right, k)
函数 partition(arr, left, right):
// 这里为了简单,选择最右元素作为主元
pivot = arr[right]
i = left // i指向比主元小的区域的边界
对于 j 从 left 到 right-1:
如果 arr[j] <= pivot:
交换 arr[i] 和 arr[j]
i = i + 1
// 将主元放到正确位置
交换 arr[i] 和 arr[right]
返回 i // 返回主元的最终位置
最好为O(n)
最坏为O(n2)
分治法就像生活中“大事化小”的智慧,用来找第k小的数特别高效。它的核心是三步走:先把数组按某个基准值分成左右两半,左边都比基准小,右边都比基准大;然后看基准的位置,如果正好是第k个就直接返回,如果不是就只在左边或右边一半里继续找。这个巧妙的设计让算法不用完全排序就能快速定位目标,最好情况下每次都能对半分解,时间复杂度是O(n);但如果运气差每次基准都选到极端值,就会退化成O(n²)。不过通过随机选择基准可以极大避免最坏情况。学完分治法我最大的体会是,真正高效的处理不仅在于如何分解问题,更在于懂得舍弃无关的部分——就像这个算法每次递归都果断抛弃不包含答案的那一半,这种有选择的专注比盲目处理全部数据要聪明得多。
浙公网安备 33010602011771号