算法第二章实践作业

1.找第k小的数的分治算法描述(自然语言):

  • 函数 'partition':
    • 选择数组的最后一个元素 'a[right]' 作为基准值 'x' 。
    • 初始化一个指针 'i' ,指向 'left - 1' 。
    • 遍历从 'left'到 'right - 1' 的元素 'a[j]':
      • 如果 'a[j]' 小于等于基准值 'x' ,则将 'i' 右移一位,然后交换 'a[j]' 和 'a[i]' 。这样做的目的是将小于等于基准值的元素放在左边,大于基准值的元素放在右边。
    • 遍历结束后,将基准值 'a[right]' 与 'a[i + 1]' 交换,此时 'a[i + 1]' 就是基准值在排好序后的正确位置,返回 'i + 1' 。
  • 函数 'find':
    • 调用'partition'函数对数组 'a' 在 '[left, right]' 区间进行划分,得到基准值的位置 'x' 。
    • 如果基准值的位置 'x' 恰好等于 'k',则直接返回 'a[x]',因为找到了第 'k' 小的数。
    • 如果 'x' 大于 'k' ,说明第 'k' 小的数在基准值的左边,递归调用 'find' 函数在 '[left, x - 1]' 区间内寻找第 'k' 小的数。
    • 如果 'x' 小于 'k' ,说明第 'k' 小的数在基准值的右边,递归调用 'find' 函数在 '[x + 1, right]' 区间内寻找第 'k' 小的数。
  • 主函数 'main':
    • 输入数组的大小 'n' 和要找的第 'k' 小的数的位置 'k' 。
    • 输入数组的元素 'a[i]' 。
    • 调用 'find'函数在数组 'a' 中寻找第 'k' 小的数并输出。
  1. 算法时间复杂度分析:

    • 最好情况:每次划分都能将数组恰好分成两个长度相等的子数组。每次划分的时间复杂度为O(n),假设数组长度为n,递归深度为log n,所以最好时间复杂度为O(n \ log n)。这是因为每次划分后,问题规模减半,总共需要划分log n次,每次划分需要线性时间O(n)。
    • 最坏情况:每次划分都将数组划分为一个长度为1和一个长度为n - 1的子数组。例如,数组已经有序,每次选择的基准值都是最大或最小的元素。此时,每次划分的时间复杂度为O(n),需要划分n - 1次,所以最坏时间复杂度为O(n^2)。
  2. 对分治法的体会和思考:

    • 优势:分治法将一个复杂的问题分解为多个规模较小的子问题,这些子问题与原问题具有相同的结构,通过递归求解子问题并合并结果来解决原问题。它能够有效地降低问题的复杂度,在很多情况下能够提高算法的效率。例如,归并排序和快速排序都是基于分治法的思想,它们的平均时间复杂度都优于简单的排序算法。
    • 适用场景:适用于问题可以分解为多个独立的子问题,且子问题的解可以合并成原问题的解的情况。像寻找第k小的数,通过划分将数组分成两部分,分别在不同部分中寻找,符合分治法的应用场景。
    • 挑战:分治法通常伴随着递归调用,这可能会带来额外的空间开销,因为每次递归调用都需要在栈中保存一些信息。此外,如何合理地划分问题是分治法的关键,如果划分不合理,如在最坏情况下的快速排序,可能导致算法的时间复杂度恶化。在实际应用中,需要根据具体问题的特点来选择合适的划分策略,以达到较好的时间和空间性能。
posted @ 2025-11-02 15:17  续雾晚  阅读(4)  评论(0)    收藏  举报