第四章:基础算法思想
欢迎来到“通用剑法篇”。如果说第一部分“基础心法篇”我们修炼的是内力,武装了Python这把神兵利器,那么从本章开始,我们将正式学习具体的“剑法招式”。这些招式——贪心、模拟、枚举、递推与分治——是算法世界中最普适、最基础的思想,也是构成更复杂算法的“基本功”。
掌握好这些基础算法思想,你将能够解决大部分普及组难度的题目,并为后续学习动态规划、图论等高阶算法打下坚实的基础。在本章,我们将彻底贯彻本书的核心理念:用最Pythonic的方式,去理解和实现这些经典算法思想。
4.1 贪心 (Greedy):局部最优解的智慧
贪心算法,顾名思义,就是“贪婪地”做出选择。在面临一个需要多步决策的问题时,它在每一步都选择当前看起来最好、最优的选项,寄希望于一系列的局部最优解能够最终导向全局最优解。
这是一种简单、高效的思想,但它并不总是正确的。使用贪心算法的诀窍在于判断“局部最优”是否真的能推出“全局最优”。这个证明过程在算法竞赛中我们往往会选择性地忽略,更多是依靠直觉、经验或者题目的暗示(例如,数据范围暗示了只能使用低复杂度的算法)。
核心思想:
- 建立评价标准: 确定一个标准,用于衡量每一步决策的“好坏”(例如,价值最大、耗时最少、结束时间最早等)。
- 循环决策: 在一个循环中,或通过排序,不断地根据评价标准做出当前最优的选择。
- 组合解: 将每一步的局部最优选择组合起来,形成问题的最终解。
【实战场景1:活动安排问题】
这是一个经典的贪心算法应用场景。
-
问题描述: 假设有n个活动,每个活动都有一个开始时间 sis_isi 和一个结束时间 fif_ifi。你只有一个会议室,问最多可以安排多少个活动,使得这些活动的时间不冲突。
-
思路分析: 如何选择才是“贪心”的?
- 选择开始最早的? 反例:一个开始很早但持续时间很长的活动,可能会“锁死”会议室,导致错过多个持续时间短的活动。
- 选择持续时间最短的? 反例:一个持续时间很短但恰好在两个长时间活动之间的活动,选择它可能会导致错过那两个活动。
- 正确的贪心策略:选择结束时间最早的活动。 为什么?因为选择结束时间最早的活动,可以尽快地释放会议室资源,为后续安排更多的活动提供可能性。这确保了局部最优(尽快结束)能够导向全局最优(安排活动最多)。
-
Pythonic实现:
在Python中,这个策略的实现极其优雅。我们只需要将所有活动存入一个列表,然后根据每个活动的结束时间进行排序即可。def schedule_activities(activities): """ 解决活动安排问题 :param activities: 一个列表,每个元素是形如 (start_time, end_time) 的元组 :return: 最多可以安排的活动数量 """ if not activities: return 0 # 核心:按活动的结束时间升序排序 # a[1] 代表元组的第二个元素,即结束时间 activities.sort(key=lambda a: a[1]) count = 1 # 第一个活动(结束时间最早的)必定入选 last_end_time = activities[0][1] # 遍历剩余的活动 for i in range(1, len(activities)): current_start_time = activities[i][0] # 如果当前活动的开始时间晚于或等于上一个已安排活动的结束时间 # 说明不冲突,可以安排 if current_start_time >= last_end_time: count += 1 last_end_time = activities[i][1] return count # --- 示例 --- # 活动列表:[(开始时间, 结束时间), ...] acts = [(1, 4), (3, 5), (0, 6

最低0.47元/天 解锁文章
640

被折叠的 条评论
为什么被折叠?



