1. 递归算法入门:从汉诺塔到链表操作
递归是算法学习中最迷人的概念之一,它像一面镜子,映照出问题的本质。我第一次接触递归是在大学的数据结构课上,当时教授用汉诺塔问题作为开场,那个瞬间仿佛打开了新世界的大门。递归的魅力在于它能将复杂问题分解成相同结构的子问题,这种"分而治之"的思想贯穿了整个算法领域。
1.1 递归的核心思想
递归算法有三个关键特征:
- 自相似性:问题可以分解为结构相同的子问题
- 边界条件:存在明确的递归终止条件
- 递推关系:子问题的解能够组合成原问题的解
理解递归最好的方式就是通过经典案例。汉诺塔问题完美展示了这些特征:移动n个盘子的问题被分解为移动n-1个盘子的子问题,当只剩1个盘子时直接移动(边界条件),而子问题的解通过特定步骤组合成原问题的解。
递归思维的关键在于相信:假设我们已经解决了更小规模的相同问题,如何利用这个解来构建当前问题的解。这种"相信"在编程中体现为函数调用自身。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 汉诺塔问题深度解析
2.1 问题描述与直观理解
汉诺塔问题描述如下:有三根柱子A、B、C,柱子A上有n个大小不一的盘子,小的在上大的在下。目标是将所有盘子从A移动到C,移动时需要遵守:
- 每次只能移动一个盘子
- 任何时候大盘子不能压在小盘子上
我第一次尝试解决3个盘子的汉诺塔时,花了整整一个下午才理清移动顺序。后来发现,关键在于将问题分解:
- 把n-1个盘子看作一个整体
- 先把这个整体移到辅助柱子
- 移动最大的盘子到目标柱
- 最后把n-1个盘子移到目标柱
2.2 递归关系建立
基于上述观察,我们可以建立递归关系:
- 将n-1个盘子从起始柱A借助目标柱C移动到辅助柱B
- 将第n个盘子(最大的)直接从A移动到C
- 将n-1个盘子从B借助A移动到C
这个关系对任意n>1都成立,当n=1时直接移动即可。这就是递归的边界条件。
2.3 代码实现与时间复杂度分析
java复制class Solution {
public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
int n = A.size();
dfs(n, A, B,
