Files
hsa/Html/apps/static/68bacdfadf5aeae0912f7f18-第三周-分治策略进阶与主方法.html
2025-09-28 21:33:00 +08:00

116 lines
5.1 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 你的其他样式 -->
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script>
MathJax.config = {
tex: {
inlineMath: [['$', '$'], ['\(', '\)']]
},
svg: {
fontCache: 'global'
}
};
</script>
</head>
<body>
<h1>分治策略进阶与主方法</h1>
<blockquote>
<p>Auto-generated at 2025-09-22 15:44</p>
</blockquote>
<h2>分治策略进阶与主方法</h2>
<h3>第一关:理论学习:主方法 (Master Theorem)</h3>
<h4>任务:掌握主方法</h4>
<h5>场景介绍</h5>
<p>在分析归并排序时,我们通过递推关系<eq>T(n)=2T(n/2)+Θ(n)</eq>得出了 O(nlogn) 的结论。但每次都画递归树很繁琐。主方法为形如 T(n)=aT(n/b)+f(n) 的递推式提供了一个“公式化”的求解捷径。</p>
<h5>思考题</h5>
<p>请与右侧的Agent你的项目经理对话学习并应用主方法</p>
<ol>
<li>
<p><strong>回顾与识别</strong>:对于归并排序的递推式 <eq>T(n)=2T(n/2)+Θ(n)</eq>,请指出主方法公式中对应的 <code>a</code><code>b</code><code>f(n)</code> 分别是什么?</p>
</li>
<li>
<p><strong>核心比较</strong>:主方法的核心是比较 <code>f(n)</code><eq>nlog_ba</eq> 的大小。请计算出归并排序中<eq>nlog_ba</eq> 的值,并判断它与 <code>f(n)</code> 的关系符合主方法的哪种情况Case</p>
</li>
<li>
<p><strong>实战演练</strong>:现在,运用你学到的主方法,求解以下几种在算法分析中常见的递推式,并说明你分别应用了主方法的哪种情况。</p>
<ul>
<li>a. <eq>T(n)=2T(n/4)+\sqrt n</eq></li>
<li>b.<eq>T(n)=7T(n/2)+n^2</eq> (这是Strassen矩阵乘法算法的复杂度模型)</li>
<li>c. <eq>T(n)=7T(n/3)+n^2</eq></li>
</ul>
</li>
</ol>
<h3>第二关:编程实践:最大子数组问题</h3>
<h4>任务:编码与分析</h4>
<h5>场景介绍</h5>
<p>我们的任务是分析每日交通流量的<strong>变化数组</strong>(正数代表流量增加,负数代表减少),并找到哪一个<strong>连续时段</strong>的流量总增量最大。这在算法上被称为“最大子数组问题” 6666。例如对于流量变化数组<code>[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]</code>总增量最大的连续时段是从第8天到第11天总增量为 <code>18 + 20 - 7 + 12 = 43</code>
虽然这个问题可以通过O(n2) 的暴力法求解,但我们将使用更高效的分治策略。</p>
<h5>题目:最大交通流量增量</h5>
<p>你需要实现一个分治算法来解决最大子数组问题。同时,为了对比,你也会实现一个暴力求解算法。</p>
<h5>代码框架</h5>
<p>在下方代码编辑区,完成 <code>find_maximum_subarray</code>(分治法)和 <code>find_max_crossing_subarray</code> 以及 <code>find_maximum_subarray_brute</code>(暴力法)三个函数。</p>
<pre><code class="language-python">import time
import random
def find_maximum_subarray_brute(arr):
&quot;&quot;&quot;
使用暴力法求解最大子数组问题
返回: (最大和, 开始索引, 结束索引)
&quot;&quot;&quot;
#--- 本周任务:请在下方实现分治算法 ---
def find_max_crossing_subarray(arr, low, mid, high):
&quot;&quot;&quot;
找到跨越中点的最大子数组
返回: (最大和, 开始索引, 结束索引)
&quot;&quot;&quot;
# TODO: 实现寻找跨越中点的最大子数组的逻辑
# 提示: 从mid向左和向右分别扫描找到各自的最大和
def find_maximum_subarray(arr, low, high):
&quot;&quot;&quot;
使用分治法求解最大子数组问题
返回: (最大和, 开始索引, 结束索引)
&quot;&quot;&quot;
# TODO: 实现分治递归逻辑
# 提示: 递归基是当数组只有一个元素时
#--- 测试与对比部分 ---
traffic_changes = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
print(f&quot;交通流量变化数据: {traffic_changes}&quot;)
#使用分治法
max_sum_dc, start_dc, end_dc = find_maximum_subarray(traffic_changes, 0, len(traffic_changes) - 1)
print(f&quot;分治法结果: 最大增量 = {max_sum_dc}, 时段 = Day {start_dc} to Day {end_dc}&quot;)
#使用暴力法验证
max_sum_brute, start_brute, end_brute = find_maximum_subarray_brute(traffic_changes)
print(f&quot;暴力法结果: 最大增量 = {max_sum_brute}, 时段 = Day {start_brute} to Day {end_brute}&quot;)
#性能测试
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&quot;\n在 n=2000 的数据集上,分治法耗时: {dc_time:.2f} ms&quot;)
start_time = time.perf_counter()
find_maximum_subarray_brute(large_data)
brute_time = (time.perf_counter() - start_time) * 1000
print(f&quot;在 n=2000 的数据集上,暴力法耗时: {brute_time:.2f} ms&quot;)</code></pre>
</body>
</html>