<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>mercerBlog</title><link>https://blog.luohaoblog.cn/</link><description>Good Luck To You!</description><item><title>LeetCode #746 最小花费爬楼梯：动态规划经典</title><link>https://blog.luohaoblog.cn/?id=5</link><description>&lt;h1&gt;🧗‍♂️ LeetCode #746 最小花费爬楼梯：动态规划经典&lt;/h1&gt;&lt;p&gt;给定一个整数数组 &lt;code&gt;cost&lt;/code&gt;，其中 &lt;code&gt;cost[i]&lt;/code&gt; 表示从第 &lt;code&gt;i&lt;/code&gt; 个台阶向上爬需要支付的费用。支付费用后，你可以选择爬 1 或 2 个台阶。你可以从下标 0 或 1 开始，目标是到达楼梯顶部（超出数组的最后一步）。请计算到达楼梯顶部的最低花费。&lt;/p&gt;&lt;p&gt;本文将详细解析题目，提供三种 Go 语言实现方式，帮助你从递归到动态规划逐步掌握！&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;📜 题目描述&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;来源&lt;/strong&gt;：LeetCode #746 - Min Cost Climbing Stairs&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;br/&gt;给定整数数组 &lt;code&gt;cost&lt;/code&gt;，&lt;code&gt;cost[i]&lt;/code&gt; 是从第 &lt;code&gt;i&lt;/code&gt; 个台阶向上爬的费用。支付费用后，可选择爬 1 或 2 个台阶。你可以从下标 0 或 1 开始，计算到达楼梯顶部（第 &lt;code&gt;n&lt;/code&gt; 步）的最低花费。&lt;/p&gt;&lt;h3&gt;示例 1&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;cost = [10,15,20]&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;15&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;br/&gt;从下标 1 开始：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;支付 15，爬 2 个台阶到达顶部。&lt;br/&gt;总花费为 15。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;示例 2&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;cost = [1,100,1,1,1,100,1,1,100,1]&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;6&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;br/&gt;从下标 0 开始：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;支付 1，爬 2 阶到下标 2。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;支付 1，爬 2 阶到下标 4。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;支付 1，爬 2 阶到下标 6。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;支付 1，爬 1 阶到下标 7。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;支付 1，爬 2 阶到下标 9。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;支付 1，爬 1 阶到顶部。&lt;br/&gt;总花费为 6。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;约束&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;2 &amp;lt;= cost.length &amp;lt;= 1000&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;0 &amp;lt;= cost[i] &amp;lt;= 999&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;💡 解题思路&lt;/h2&gt;&lt;h3&gt;核心观察&lt;/h3&gt;&lt;p&gt;要到达楼梯顶部（第 &lt;code&gt;n&lt;/code&gt; 步），你必须从第 &lt;code&gt;n-1&lt;/code&gt; 或 &lt;code&gt;n-2&lt;/code&gt; 个台阶爬上来。因此，到达第 &lt;code&gt;i&lt;/code&gt; 个台阶的最低花费可以表示为：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;从 &lt;code&gt;i-1&lt;/code&gt; 爬 1 步：需支付 &lt;code&gt;cost[i-1]&lt;/code&gt; 加上到达 &lt;code&gt;i-1&lt;/code&gt; 的最低花费。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;从 &lt;code&gt;i-2&lt;/code&gt; 爬 2 步：需支付 &lt;code&gt;cost[i-2]&lt;/code&gt; 加上到达 &lt;code&gt;i-2&lt;/code&gt; 的最低花费。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;状态转移方程：&lt;/p&gt;&lt;pre&gt;dp[i]&amp;nbsp;=&amp;nbsp;min(dp[i-1]&amp;nbsp;+&amp;nbsp;cost[i-1],&amp;nbsp;dp[i-2]&amp;nbsp;+&amp;nbsp;cost[i-2])&lt;/pre&gt;&lt;p&gt;初始条件：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dp[0] = 0&lt;/code&gt;（从下标 0 开始，初始花费为 0）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dp[1] = 0&lt;/code&gt;（从下标 1 开始，初始花费为 0）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;小贴士&lt;/strong&gt;：楼梯顶部是第 &lt;code&gt;n&lt;/code&gt; 步，需计算 &lt;code&gt;dp[n]&lt;/code&gt;。本题与爬楼梯问题类似，但增加了费用优化。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🚀 Go 语言实现&lt;/h2&gt;&lt;p&gt;以下是三种 Go 语言实现方式，从递归到动态规划逐步优化，适合不同场景。代码块使用 &lt;code&gt;go&lt;/code&gt; 语法高亮，建议在富文本编辑器中启用深色主题（如 &lt;code&gt;monokai&lt;/code&gt; 或 &lt;code&gt;dracula&lt;/code&gt;）以增强可读性。&lt;/p&gt;&lt;h3&gt;方法 1：递归 + 记忆化&lt;/h3&gt;&lt;p&gt;通过递归解决，使用记忆化数组避免重复计算。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;minCostClimbingStairs(cost&amp;nbsp;[]int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;n&amp;nbsp;:=&amp;nbsp;len(cost)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memo&amp;nbsp;:=&amp;nbsp;make([]int,&amp;nbsp;n+1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;dfs(n,&amp;nbsp;cost,&amp;nbsp;memo)
}

func&amp;nbsp;dfs(i&amp;nbsp;int,&amp;nbsp;cost,&amp;nbsp;memo&amp;nbsp;[]int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;1&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;memo[i]&amp;nbsp;!=&amp;nbsp;0&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;memo[i]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memo[i]&amp;nbsp;=&amp;nbsp;min(dfs(i-1,&amp;nbsp;cost,&amp;nbsp;memo)+cost[i-1],&amp;nbsp;dfs(i-2,&amp;nbsp;cost,&amp;nbsp;memo)+cost[i-2])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;memo[i]
}

func&amp;nbsp;min(a,&amp;nbsp;b&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;a&amp;nbsp;&amp;lt;&amp;nbsp;b&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;a
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;b
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(minCostClimbingStairs([]int{10,&amp;nbsp;15,&amp;nbsp;20}))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;15
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(minCostClimbingStairs([]int{1,&amp;nbsp;100,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;100,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;100,&amp;nbsp;1}))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;6
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：直观，体现递归思想&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：需要额外内存存储记忆化数组&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h3&gt;方法 2：动态规划（DP 数组）&lt;/h3&gt;&lt;p&gt;使用数组存储每个台阶的最低花费，迭代计算。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;minCostClimbingStairs(cost&amp;nbsp;[]int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;n&amp;nbsp;:=&amp;nbsp;len(cost)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp&amp;nbsp;:=&amp;nbsp;make([]int,&amp;nbsp;n+1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[0],&amp;nbsp;dp[1]&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;:=&amp;nbsp;2;&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;n;&amp;nbsp;i++&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[i]&amp;nbsp;=&amp;nbsp;min(dp[i-1]+cost[i-1],&amp;nbsp;dp[i-2]+cost[i-2])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;dp[n]
}

func&amp;nbsp;min(a,&amp;nbsp;b&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;a&amp;nbsp;&amp;lt;&amp;nbsp;b&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;a
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;b
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(minCostClimbingStairs([]int{10,&amp;nbsp;15,&amp;nbsp;20}))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;15
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(minCostClimbingStairs([]int{1,&amp;nbsp;100,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;100,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;100,&amp;nbsp;1}))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;6
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：逻辑清晰，适合初学者理解动态规划&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：空间占用较多&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h3&gt;方法 3：空间优化（滚动变量）🔥&lt;/h3&gt;&lt;p&gt;仅用两个变量存储前两步的最低花费，优化空间复杂度。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;minCostClimbingStairs(cost&amp;nbsp;[]int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;n&amp;nbsp;:=&amp;nbsp;len(cost)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prev,&amp;nbsp;curr&amp;nbsp;:=&amp;nbsp;0,&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;:=&amp;nbsp;2;&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;n;&amp;nbsp;i++&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next&amp;nbsp;:=&amp;nbsp;min(curr+cost[i-1],&amp;nbsp;prev+cost[i-2])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prev&amp;nbsp;=&amp;nbsp;curr
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;curr&amp;nbsp;=&amp;nbsp;next
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;curr
}

func&amp;nbsp;min(a,&amp;nbsp;b&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;a&amp;nbsp;&amp;lt;&amp;nbsp;b&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;a
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;b
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(minCostClimbingStairs([]int{10,&amp;nbsp;15,&amp;nbsp;20}))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;15
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(minCostClimbingStairs([]int{1,&amp;nbsp;100,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;100,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;100,&amp;nbsp;1}))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;6
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(1)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：高效简洁，面试最佳写法&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;推荐指数&lt;/strong&gt;：⭐⭐⭐⭐⭐&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;📊 方法对比&lt;/h2&gt;&lt;table&gt;&lt;thead&gt;&lt;tr class=&quot;firstRow&quot;&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;时间复杂度&lt;/th&gt;&lt;th&gt;空间复杂度&lt;/th&gt;&lt;th&gt;推荐指数&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;递归 + 记忆化&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;⭐⭐⭐☆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DP 数组&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;滚动变量（最优）&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：由于 &lt;code&gt;cost[i] &amp;lt;= 999&lt;/code&gt; 且 &lt;code&gt;cost.length &amp;lt;= 1000&lt;/code&gt;，结果不会溢出 Go 的 &lt;code&gt;int&lt;/code&gt; 类型。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🎯 进阶思考&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;扩展步长&lt;/strong&gt;：如果可以爬 1、2 或 3 个台阶？&lt;br/&gt;状态转移方程需考虑更多前驱状态：&lt;code&gt;dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2], dp[i-3] + cost[i-3])&lt;/code&gt;。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;动态费用&lt;/strong&gt;：如果费用随时间变化？&lt;br/&gt;需引入时间维度，调整 DP 模型。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;更高效率&lt;/strong&gt;：能否用其他优化方法？&lt;br/&gt;对于特定输入，可能通过数学规律或预处理进一步优化。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;学习建议&lt;/strong&gt;：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;初学者：从递归和 DP 数组入手，理解状态转移。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;进阶者：掌握滚动变量优化，体会空间优化的精髓。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;高手：探索扩展问题，尝试更复杂的动态规划场景。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🔚 总结&lt;/h2&gt;&lt;p&gt;“最小花费爬楼梯”问题是动态规划的经典变种，核心在于状态转移方程 &lt;code&gt;dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])&lt;/code&gt;。通过三种 Go 实现（递归、DP 数组、滚动变量），我们可以从直观到高效逐步优化。&lt;/p&gt;&lt;p&gt;希望这篇文章帮你彻底掌握最小花费爬楼梯问题！如果觉得有用，欢迎点赞分享 💖，也欢迎留言讨论更多算法题！&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 05 Sep 2025 13:45:33 +0800</pubDate></item><item><title>LeetCode #509 斐波那契数</title><link>https://blog.luohaoblog.cn/?id=4</link><description>&lt;h1&gt;🔢 LeetCode #509 斐波那契数：动态规划入门经典&lt;/h1&gt;&lt;p&gt;斐波那契数列是一个经典的算法问题，定义为从 0 和 1 开始，每一项是前两项之和。本文将详细解析题目，分享三种 Go 语言实现方式，帮助你从递归到动态规划逐步掌握！&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;📜 题目描述&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;来源&lt;/strong&gt;：LeetCode #509 - Fibonacci Number&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;br/&gt;给定非负整数 &lt;code&gt;n&lt;/code&gt;，计算斐波那契数列的第 &lt;code&gt;n&lt;/code&gt; 项 &lt;code&gt;F(n)&lt;/code&gt;，其中：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;F(0) = 0&lt;/code&gt;，&lt;code&gt;F(1) = 1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;F(n) = F(n-1) + F(n-2)&lt;/code&gt;，对于 &lt;code&gt;n &amp;gt; 1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;示例 1&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;n = 2&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;1&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;code&gt;F(2) = F(1) + F(0) = 1 + 0 = 1&lt;/code&gt;&lt;/p&gt;&lt;h3&gt;示例 2&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;n = 3&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;2&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;code&gt;F(3) = F(2) + F(1) = 1 + 1 = 2&lt;/code&gt;&lt;/p&gt;&lt;h3&gt;示例 3&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;n = 4&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;3&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;code&gt;F(4) = F(3) + F(2) = 2 + 1 = 3&lt;/code&gt;&lt;/p&gt;&lt;h3&gt;约束&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;0 &amp;lt;= n &amp;lt;= 30&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;💡 解题思路&lt;/h2&gt;&lt;h3&gt;核心观察&lt;/h3&gt;&lt;p&gt;斐波那契数列的核心是状态转移方程：&lt;/p&gt;&lt;pre&gt;F(n)&amp;nbsp;=&amp;nbsp;F(n-1)&amp;nbsp;+&amp;nbsp;F(n-2)&lt;/pre&gt;&lt;p&gt;初始条件：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;F(0) = 0&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;F(1) = 1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这个问题可以通过递归或动态规划解决。直接递归会导致重复计算，因此我们可以使用记忆化或动态规划优化性能。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;小贴士&lt;/strong&gt;：斐波那契数列广泛应用于算法问题，如爬楼梯、矩阵快速幂等。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🚀 Go 语言实现&lt;/h2&gt;&lt;p&gt;以下是三种 Go 语言实现方式，从递归到动态规划逐步优化，适合不同场景。代码块使用 &lt;code&gt;go&lt;/code&gt; 语法高亮，建议在富文本编辑器中启用深色主题（如 &lt;code&gt;monokai&lt;/code&gt; 或 &lt;code&gt;dracula&lt;/code&gt;）以增强可读性。&lt;/p&gt;&lt;h3&gt;方法 1：递归 + 记忆化&lt;/h3&gt;&lt;p&gt;通过递归解决，使用记忆化数组避免重复计算。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;fib(n&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memo&amp;nbsp;:=&amp;nbsp;make([]int,&amp;nbsp;n+1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;dfs(n,&amp;nbsp;memo)
}

func&amp;nbsp;dfs(n&amp;nbsp;int,&amp;nbsp;memo&amp;nbsp;[]int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;n&amp;nbsp;&amp;lt;=&amp;nbsp;1&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;n
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;memo[n]&amp;nbsp;!=&amp;nbsp;0&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;memo[n]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memo[n]&amp;nbsp;=&amp;nbsp;dfs(n-1,&amp;nbsp;memo)&amp;nbsp;+&amp;nbsp;dfs(n-2,&amp;nbsp;memo)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;memo[n]
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(fib(2))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(fib(3))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(fib(4))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;3
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：直观，易于理解递归思想&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：需要额外内存存储记忆化数组&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h3&gt;方法 2：动态规划（DP 数组）&lt;/h3&gt;&lt;p&gt;使用数组存储每个斐波那契数，迭代计算。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;fib(n&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;n&amp;nbsp;&amp;lt;=&amp;nbsp;1&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;n
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp&amp;nbsp;:=&amp;nbsp;make([]int,&amp;nbsp;n+1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[0]&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[1]&amp;nbsp;=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;:=&amp;nbsp;2;&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;n;&amp;nbsp;i++&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[i]&amp;nbsp;=&amp;nbsp;dp[i-1]&amp;nbsp;+&amp;nbsp;dp[i-2]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;dp[n]
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(fib(4))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;3
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：逻辑清晰，适合初学者理解动态规划&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：空间占用较多&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h3&gt;方法 3：空间优化（滚动变量）🔥&lt;/h3&gt;&lt;p&gt;仅用两个变量存储前两项，优化空间复杂度。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;fib(n&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;n&amp;nbsp;&amp;lt;=&amp;nbsp;1&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;n
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prev,&amp;nbsp;curr&amp;nbsp;:=&amp;nbsp;0,&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;:=&amp;nbsp;2;&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;n;&amp;nbsp;i++&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next&amp;nbsp;:=&amp;nbsp;prev&amp;nbsp;+&amp;nbsp;curr
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prev&amp;nbsp;=&amp;nbsp;curr
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;curr&amp;nbsp;=&amp;nbsp;next
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;curr
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(fib(4))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;3
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(1)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：高效简洁，面试最佳写法&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;推荐指数&lt;/strong&gt;：⭐⭐⭐⭐⭐&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;📊 方法对比&lt;/h2&gt;&lt;table&gt;&lt;thead&gt;&lt;tr class=&quot;firstRow&quot;&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;时间复杂度&lt;/th&gt;&lt;th&gt;空间复杂度&lt;/th&gt;&lt;th&gt;推荐指数&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;递归 + 记忆化&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;⭐⭐⭐☆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DP 数组&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;滚动变量（最优）&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：对于 &lt;code&gt;n &amp;lt;= 30&lt;/code&gt;，结果不会溢出 Go 的 &lt;code&gt;int&lt;/code&gt; 类型。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🎯 进阶思考&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;扩展定义&lt;/strong&gt;：如果初始条件变为 &lt;code&gt;F(0) = 1&lt;/code&gt;, &lt;code&gt;F(1) = 2&lt;/code&gt;？&lt;br/&gt;需调整初始值，逻辑不变。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;更高效率&lt;/strong&gt;：能否用矩阵快速幂实现 O(log n) 时间复杂度？&lt;br/&gt;斐波那契数列可用矩阵形式 &lt;code&gt;[F(n), F(n-1)] = [[1,1],[1,0]]^(n-1) * [F(1), F(0)]&lt;/code&gt; 优化。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;实际应用&lt;/strong&gt;：斐波那契数列在爬楼梯、股票买卖等算法问题中有广泛应用。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;学习建议&lt;/strong&gt;：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;初学者：从递归和 DP 数组入手，理解状态转移。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;进阶者：掌握滚动变量优化，体会空间优化的精髓。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;高手：尝试矩阵快速幂，挑战 O(log n) 解法。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🔚 总结&lt;/h2&gt;&lt;p&gt;斐波那契数列问题是动态规划的入门经典，核心在于状态转移方程 &lt;code&gt;F(n) = F(n-1) + F(n-2)&lt;/code&gt;。通过三种 Go 实现（递归、DP 数组、滚动变量），我们可以从直观到高效逐步优化。&lt;/p&gt;&lt;p&gt;希望这篇文章帮你彻底掌握斐波那契数列！如果觉得有用，欢迎点赞分享 💖，也欢迎留言讨论更多算法题！&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 05 Sep 2025 11:51:57 +0800</pubDate></item><item><title>LeetCode #70 爬楼梯(动态规划)</title><link>https://blog.luohaoblog.cn/?id=3</link><description>&lt;h1&gt;🧗‍♂️ LeetCode #70 爬楼梯：动态规划入门经典&lt;/h1&gt;&lt;p&gt;假设你正在爬楼梯，需要 &lt;code&gt;n&lt;/code&gt; 阶才能到达楼顶。每次你可以选择爬 &lt;strong&gt;1&lt;/strong&gt; 或 &lt;strong&gt;2&lt;/strong&gt; 个台阶。问：有多少种不同的方法可以爬到楼顶？&lt;/p&gt;&lt;p&gt;这是动态规划的经典入门题，常见于 LeetCode、算法面试和编程教学中。本文将详细解析题目，分享三种 Go 语言实现方式，并提供进阶思考，助你彻底掌握！&lt;/p&gt;&lt;hr/&gt;&lt;h2&gt;📜 题目描述&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;来源&lt;/strong&gt;：LeetCode #70 - Climbing Stairs&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;br/&gt;每次你可以爬 1 或 2 个台阶。给定正整数 &lt;code&gt;n&lt;/code&gt;，计算到达楼顶的不同方法数。&lt;/p&gt;&lt;h3&gt;示例 1&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;n = 2&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;2&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;1 阶 + 1 阶&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;2 阶&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;示例 2&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;n = 3&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;code&gt;3&lt;/code&gt;&lt;br/&gt;&lt;strong&gt;解释&lt;/strong&gt;：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;1 阶 + 1 阶 + 1 阶&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;1 阶 + 2 阶&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;2 阶 + 1 阶&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;约束&lt;/h3&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;1 &amp;lt;= n &amp;lt;= 45&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;💡 解题思路&lt;/h2&gt;&lt;h3&gt;核心观察&lt;/h3&gt;&lt;p&gt;要到达第 &lt;code&gt;n&lt;/code&gt; 阶楼梯，只能从以下两种情况到达：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;从第 &lt;code&gt;n-1&lt;/code&gt; 阶爬 1 步&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;从第 &lt;code&gt;n-2&lt;/code&gt; 阶爬 2 步&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;因此，到达第 &lt;code&gt;n&lt;/code&gt; 阶的方法数为：&lt;/p&gt;&lt;pre&gt;f(n)&amp;nbsp;=&amp;nbsp;f(n-1)&amp;nbsp;+&amp;nbsp;f(n-2)&lt;/pre&gt;&lt;p&gt;这与斐波那契数列高度相似，初始条件为：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;f(1) = 1&lt;/code&gt;（1 种方法）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;f(2) = 2&lt;/code&gt;（2 种方法）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;小贴士&lt;/strong&gt;：本题本质是斐波那契数列的变种，例如：&lt;code&gt;f(3) = 3&lt;/code&gt;, &lt;code&gt;f(4) = 5&lt;/code&gt;。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🚀 Go 语言实现&lt;/h2&gt;&lt;p&gt;以下是三种 Go 语言实现方式，从递归到动态规划，逐步优化，适合不同场景。代码块已标注语言为 &lt;code&gt;go&lt;/code&gt;，建议在富文本编辑器中启用深色主题（如 &lt;code&gt;monokai&lt;/code&gt; 或 &lt;code&gt;dracula&lt;/code&gt;）以增强视觉效果。&lt;/p&gt;&lt;h3&gt;方法 1：递归 + 记忆化&lt;/h3&gt;&lt;p&gt;通过递归解决，使用记忆化避免重复计算。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;climbStairs(n&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memo&amp;nbsp;:=&amp;nbsp;make([]int,&amp;nbsp;n+1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;dfs(n,&amp;nbsp;memo)
}

func&amp;nbsp;dfs(n&amp;nbsp;int,&amp;nbsp;memo&amp;nbsp;[]int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;n&amp;nbsp;&amp;lt;=&amp;nbsp;2&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;n
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;memo[n]&amp;nbsp;!=&amp;nbsp;0&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;memo[n]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memo[n]&amp;nbsp;=&amp;nbsp;dfs(n-1,&amp;nbsp;memo)&amp;nbsp;+&amp;nbsp;dfs(n-2,&amp;nbsp;memo)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;memo[n]
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(climbStairs(2))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(climbStairs(3))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;3
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：直观，体现递归思想&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：需要额外内存存储记忆化数组&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h3&gt;方法 2：动态规划（DP 数组）&lt;/h3&gt;&lt;p&gt;使用数组存储每个台阶的状态，迭代计算。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;climbStairs(n&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;n&amp;nbsp;&amp;lt;=&amp;nbsp;2&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;n
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp&amp;nbsp;:=&amp;nbsp;make([]int,&amp;nbsp;n+1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[1]&amp;nbsp;=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[2]&amp;nbsp;=&amp;nbsp;2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;:=&amp;nbsp;3;&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;n;&amp;nbsp;i++&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dp[i]&amp;nbsp;=&amp;nbsp;dp[i-1]&amp;nbsp;+&amp;nbsp;dp[i-2]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;dp[n]
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(climbStairs(5))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;8
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：逻辑清晰，适合初学者&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：空间占用较多&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h3&gt;方法 3：空间优化（滚动变量）🔥&lt;/h3&gt;&lt;p&gt;仅用两个变量存储前两步状态，优化空间复杂度。&lt;/p&gt;&lt;pre&gt;package&amp;nbsp;main

import&amp;nbsp;&amp;quot;fmt&amp;quot;

func&amp;nbsp;climbStairs(n&amp;nbsp;int)&amp;nbsp;int&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;n&amp;nbsp;&amp;lt;=&amp;nbsp;2&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;n
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prev,&amp;nbsp;curr&amp;nbsp;:=&amp;nbsp;1,&amp;nbsp;2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;:=&amp;nbsp;3;&amp;nbsp;i&amp;nbsp;&amp;lt;=&amp;nbsp;n;&amp;nbsp;i++&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next&amp;nbsp;:=&amp;nbsp;prev&amp;nbsp;+&amp;nbsp;curr
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prev&amp;nbsp;=&amp;nbsp;curr
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;curr&amp;nbsp;=&amp;nbsp;next
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;curr
}

func&amp;nbsp;main()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fmt.Println(climbStairs(45))&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;1836311903
}&lt;/pre&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：O(n)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;空间复杂度&lt;/strong&gt;：O(1)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：高效简洁，面试最佳写法&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;推荐指数&lt;/strong&gt;：⭐⭐⭐⭐⭐&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;📊 方法对比&lt;/h2&gt;&lt;table&gt;&lt;thead&gt;&lt;tr class=&quot;firstRow&quot;&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;时间复杂度&lt;/th&gt;&lt;th&gt;空间复杂度&lt;/th&gt;&lt;th&gt;推荐指数&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;递归 + 记忆化&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;⭐⭐⭐☆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DP 数组&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;滚动变量（最优）&lt;/td&gt;&lt;td&gt;O(n)&lt;/td&gt;&lt;td&gt;O(1)&lt;/td&gt;&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：当 &lt;code&gt;n = 45&lt;/code&gt; 时，结果为 &lt;code&gt;1836311903&lt;/code&gt;，不会溢出 Go 的 &lt;code&gt;int&lt;/code&gt; 类型。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🎯 进阶思考&lt;/h2&gt;&lt;ol class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;扩展步长&lt;/strong&gt;：如果每次可以爬 1、2 或 3 阶？&lt;br/&gt;状态转移方程变为：&lt;code&gt;f(n) = f(n-1) + f(n-2) + f(n-3)&lt;/code&gt;。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;任意步长&lt;/strong&gt;：如果允许爬 1 到 k 阶？&lt;br/&gt;类似“完全背包”问题，需调整 DP 逻辑。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;更高效率&lt;/strong&gt;：能否用矩阵快速幂达到 O(log n) 时间复杂度？&lt;br/&gt;斐波那契数列的矩阵形式可实现此优化。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;学习建议&lt;/strong&gt;：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;初学者：先掌握递归和 DP 数组写法。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;进阶者：练习滚动变量优化，理解状态转移核心。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;高手：尝试矩阵快速幂解法，挑战 O(log n)。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;🔚 总结&lt;/h2&gt;&lt;p&gt;“爬楼梯”问题是动态规划的入门经典，核心在于理解状态转移方程 &lt;code&gt;f(n) = f(n-1) + f(n-2)&lt;/code&gt;。通过三种 Go 实现（递归、DP 数组、滚动变量），我们可以从直观到高效逐步优化。&lt;/p&gt;&lt;p&gt;希望这篇文章帮你彻底掌握爬楼梯问题！如果觉得有用，欢迎点赞分享 💖，也欢迎留言讨论更多算法题！&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 05 Sep 2025 10:44:32 +0800</pubDate></item></channel></rss>