Auto-generated at 2025-09-22 15:44
在分析归并排序时,我们通过递推关系
请与右侧的Agent(你的项目经理)对话,学习并应用主方法:
回顾与识别:对于归并排序的递推式 a、b 和 f(n) 分别是什么?
核心比较:主方法的核心是比较 f(n) 与 f(n) 的关系符合主方法的哪种情况(Case)?
实战演练:现在,运用你学到的主方法,求解以下几种在算法分析中常见的递推式,并说明你分别应用了主方法的哪种情况。
我们的任务是分析每日交通流量的变化数组(正数代表流量增加,负数代表减少),并找到哪一个连续时段的流量总增量最大。这在算法上被称为“最大子数组问题” 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")