分治策略进阶与主方法

Auto-generated at 2025-09-22 15:44

分治策略进阶与主方法

第一关:理论学习:主方法 (Master Theorem)

任务:掌握主方法

场景介绍

在分析归并排序时,我们通过递推关系T(n)=2T(n/2)+Θ(n)得出了 O(nlogn) 的结论。但每次都画递归树很繁琐。主方法为形如 T(n)=aT(n/b)+f(n) 的递推式提供了一个“公式化”的求解捷径。

思考题

请与右侧的Agent(你的项目经理)对话,学习并应用主方法:

  1. 回顾与识别:对于归并排序的递推式 T(n)=2T(n/2)+Θ(n),请指出主方法公式中对应的 abf(n) 分别是什么?

  2. 核心比较:主方法的核心是比较 f(n)nlog_ba 的大小。请计算出归并排序中nlog_ba 的值,并判断它与 f(n) 的关系符合主方法的哪种情况(Case)?

  3. 实战演练:现在,运用你学到的主方法,求解以下几种在算法分析中常见的递推式,并说明你分别应用了主方法的哪种情况。

第二关:编程实践:最大子数组问题

任务:编码与分析

场景介绍

我们的任务是分析每日交通流量的变化数组(正数代表流量增加,负数代表减少),并找到哪一个连续时段的流量总增量最大。这在算法上被称为“最大子数组问题” 6666。例如,对于流量变化数组[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7],总增量最大的连续时段是从第8天到第11天,总增量为 18 + 20 - 7 + 12 = 43 。 虽然这个问题可以通过O(n2) 的暴力法求解,但我们将使用更高效的分治策略。

题目:最大交通流量增量

你需要实现一个分治算法来解决最大子数组问题。同时,为了对比,你也会实现一个暴力求解算法。

代码框架

在下方代码编辑区,完成 find_maximum_subarray(分治法)和 find_max_crossing_subarray 以及 find_maximum_subarray_brute(暴力法)三个函数。

import time
import random

def find_maximum_subarray_brute(arr):
    """
    使用暴力法求解最大子数组问题
    返回: (最大和, 开始索引, 结束索引)
    """


#--- 本周任务:请在下方实现分治算法 ---

def find_max_crossing_subarray(arr, low, mid, high):
    """
    找到跨越中点的最大子数组
    返回: (最大和, 开始索引, 结束索引)
    """
    # TODO: 实现寻找跨越中点的最大子数组的逻辑
    # 提示: 从mid向左和向右分别扫描,找到各自的最大和



def find_maximum_subarray(arr, low, high):
    """
    使用分治法求解最大子数组问题
    返回: (最大和, 开始索引, 结束索引)
    """
    # TODO: 实现分治递归逻辑
    # 提示: 递归基是当数组只有一个元素时


#--- 测试与对比部分 ---
traffic_changes = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
print(f"交通流量变化数据: {traffic_changes}")

#使用分治法
max_sum_dc, start_dc, end_dc = find_maximum_subarray(traffic_changes, 0, len(traffic_changes) - 1)
print(f"分治法结果: 最大增量 = {max_sum_dc}, 时段 = Day {start_dc} to Day {end_dc}")

#使用暴力法验证
max_sum_brute, start_brute, end_brute = find_maximum_subarray_brute(traffic_changes)
print(f"暴力法结果: 最大增量 = {max_sum_brute}, 时段 = Day {start_brute} to Day {end_brute}")

#性能测试
large_data = [random.randint(-50, 50) for _ in range(2000)]
start_time = time.perf_counter()
find_maximum_subarray(large_data, 0, len(large_data) - 1)
dc_time = (time.perf_counter() - start_time) * 1000
print(f"\n在 n=2000 的数据集上,分治法耗时: {dc_time:.2f} ms")

start_time = time.perf_counter()
find_maximum_subarray_brute(large_data)
brute_time = (time.perf_counter() - start_time) * 1000
print(f"在 n=2000 的数据集上,暴力法耗时: {brute_time:.2f} ms")