【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)

简介: 本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。

💰 动态规划实战:打家劫舍、完全平方数与零钱兑换(LeetCode 198 / 279 / 322)

本篇博客一次性带你掌握三道 LeetCode 中经典的动态规划(DP)题目:

  • 🏠 198. 打家劫舍(House Robber)
  • 🟩 279. 完全平方数(Perfect Squares)
  • 💸 322. 零钱兑换(Coin Change)

它们覆盖了动态规划中的线性状态转移完全背包问题,以及最小子结构决策问题


🏠 一、198. 打家劫舍

📌 题目描述

一排房子,每个房子里有一定金额的钱,不能偷相邻的两个房子。求最多能偷多少钱?


💡 解题思路

这是一个典型的线性动态规划问题。

dp[i] 表示前 i 个房子最多能偷的钱:

  • 偷第 i 个房子 → 前 i - 2 个房子最大值 + nums[i]
  • 不偷第 i 个房子 → 前 i - 1 个房子最大值

状态转移方程为:

dp[i] = max(dp[i-1], dp[i-2] + nums[i])
AI 代码解读

✅ Go 实现(空间优化版)

func rob(nums []int) int {
   
    if len(nums) == 0 {
   
        return 0
    }
    if len(nums) == 1 {
   
        return nums[0]
    }
    prev, curr := 0, 0
    for _, num := range nums {
   
        prev, curr = curr, max(curr, prev+num)
    }
    return curr
}

func max(a, b int) int {
   
    if a > b {
   
        return a
    }
    return b
}
AI 代码解读

🟩 二、279. 完全平方数

📌 题目描述

给你一个整数 n,将其表示为若干个完全平方数的和,求这些数的最少数量。


💡 解题思路

这是一个典型的完全背包问题。

  • 状态定义:dp[i] 表示组成 i 所需的最少平方数数量;
  • 状态转移:尝试每一个 j*j <= i 的平方数:
dp[i] = min(dp[i], dp[i - j*j] + 1)
AI 代码解读

✅ Go 实现

func numSquares(n int) int {
   
    dp := make([]int, n+1)
    for i := 1; i <= n; i++ {
   
        dp[i] = i // 最坏情况:1+1+1+...+1
        for j := 1; j*j <= i; j++ {
   
            dp[i] = min(dp[i], dp[i - j*j] + 1)
        }
    }
    return dp[n]
}

func min(a, b int) int {
   
    if a < b {
   
        return a
    }
    return b
}
AI 代码解读

💸 三、322. 零钱兑换

📌 题目描述

给定不同面额的硬币 coins 和总金额 amount,求最少的硬币数量使得总金额为 amount。如果没有一种组合能组成,返回 -1。


💡 解题思路

也是典型的完全背包问题,区别在于:

  • 目标是最小硬币数
  • 状态定义:dp[i] 表示组成金额 i 所需最少的硬币数
  • 初始化:dp[0] = 0,其余为 inf(表示不可达)

状态转移方程:

dp[i] = min(dp[i], dp[i - coin] + 1)
AI 代码解读

✅ Go 实现

func coinChange(coins []int, amount int) int {
   
    dp := make([]int, amount+1)
    for i := 1; i <= amount; i++ {
   
        dp[i] = amount + 1
    }

    for _, coin := range coins {
   
        for i := coin; i <= amount; i++ {
   
            dp[i] = min(dp[i], dp[i - coin] + 1)
        }
    }

    if dp[amount] > amount {
   
        return -1
    }
    return dp[amount]
}
AI 代码解读

🔚 总结对比

题目 本质 状态定义 特点
打家劫舍 线性DP dp[i] 表示前 i 间房最多可偷金额 不能连续取相邻元素
完全平方数 完全背包 dp[i] 表示组成 i 所需的最少平方数个数 类似零钱兑换
零钱兑换 完全背包 dp[i] 表示组成金额 i 最少硬币数 与完全平方数模型一致

📘 写在最后

这三道题虽然看起来背景完全不同,但本质上都属于一维动态规划问题,熟悉它们可以极大提升你解决复杂 DP 问题的能力。

建议继续练习类似题目:

    1. 打家劫舍 II(环形房屋)
    1. 三角形最小路径和
    1. 最长递增子序列

目录
相关文章
|
2月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
100 1
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
113 1
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
162 6
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
128 6
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
128 4
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
271 2
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
160 3
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
222 1
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
224 7
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
128 5
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问