我的第二章作业学习

一、分治算法描述(快速选择找第k小)

  1. 自然语言描述

本算法基于快速排序的划分思想,采用分治策略实现平均O(n)复杂度查找第k小数:

  1. 划分(partition):在当前数组区间[left,right]选取基准元素pivot,将区间划分成两部分:左侧所有元素≤pivot,右侧所有元素≥pivot;划分完成后基准落在其有序数组的正确下标x。

  2. 分治判断

◦ 若基准下标x恰好等于目标下标k-1(数组从0开始,第k小对应下标k-1),基准就是答案,直接返回;

◦ 若x<k-1:第k小元素只存在于右区间[x+1,right],递归处理右区间;

◦ 若x>k-1:第k小元素只存在于左区间[left,x-1],递归处理左区间。

  1. 递归边界:区间仅存一个元素(left==right),该元素即为所求。

  2. 伪代码
    // 划分函数,返回基准最终下标
    partition(a[], left, right):
    mid = left + (right - left) / 2
    pivot = a[mid]
    s = 空列表(存≤pivot)
    m = 空列表(存>pivot)
    for i = left to right:
    if i == mid: continue
    if a[i] <= pivot: s.append(a[i])
    else: m.append(a[i])
    // 回填数组
    sh = s长度
    for i = 0 to sh-1: a[left+i] = s[i]
    a[left + sh] = pivot
    for j = 0 to m长度-1: a[left+sh+1+j] = m[j]
    return left + sh

// 分治查找函数,k_target为目标下标(第k小对应k-1)
find(a[], left, right, k_target):
if left == right:
return a[left]
x = partition(a, left, right)
if x == k_target:
return a[x]
elif x < k_target:
return find(a, x+1, right, k_target)
else:
return find(a, left, x-1, k_target)

// 主流程
输入n, k
输入数组a
res = find(a, 0, n-1, k-1)
输出res
二、时间复杂度分析

  1. 最好时间复杂度:O(n)
    每次划分的基准恰好将区间均分,仅需递归处理一半子区间。总运算量为n + \frac{n}{2} + \frac{n}{4} + ... ≈ 2n,线性复杂度O(n)。

  2. 最坏时间复杂度:O(n^2)
    每次选取的基准为区间最大/最小值,划分后仅剔除1个元素,递归规模仅减少1。总运算量n+(n-1)+(n-2)+... = \frac{n(n+1)}{2},平方复杂度O(n^2)。

三、对分治法的体会与思考

  1. 分治核心逻辑:分、治、合
    分治三步为拆分大问题、递归求解子问题、合并子问题解。本题是特殊分治:无需合并,划分后只需递归求解单侧子区间,直接舍弃另一半,大幅减少计算量,这是快速选择效率优于全排序的关键。

  2. 划分质量决定算法效率
    分治算法性能高度依赖拆分方式。本算法中基准选取直接决定复杂度:均衡划分可达线性时间,极差划分会退化到平方级;随机选取基准可大幅降低最坏情况出现概率。

  3. 分治的优势:避免冗余计算
    若先完整排序再取第k小,复杂度为O(n\log n);而快速选择只需要定位目标元素,不需要完成全区间排序,跳过大量无关元素处理,体现分治“缩小问题规模、减少无效运算”的优势。

  4. 适用场景总结
    分治法适合原问题可拆分为结构相同、相互独立的子问题的场景,常通过递归实现。二分查找、快速排序、归并排序、快速选择都是典型分治应用;其中仅需单侧递归的分治算法,通常时间效率更优。

posted @ 2026-10-13 19:38  rui-ni  阅读(3)  评论(0)    收藏  举报