前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • 前端算法面试

    • 数组基础
    • 栈、队列与链表
    • 树与二叉树
    • 二叉树递归遍历
    • 时间与空间复杂度
    • 数组高频题
    • 字符串高频题
    • 链表基础题
    • 链表双指针
    • 环形链表
    • 栈的经典应用
    • 队列与双端队列
    • DFS 与 BFS
    • 递归与回溯
    • 二叉树高频题
    • 二叉搜索树
    • 平衡二叉树
    • 堆与堆排序
    • 基础排序算法
    • 归并与快速排序
    • 动态规划入门
    • 动态规划进阶
      • 0-1背包模型
        • 思路分析
      • 最长上升子序列模型
        • 思路分析
        • 问题复盘
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

普通人也能吃透的动态规划思想专题(下)|算法篇

在上一节,我们掌握了求解动态规划问题的通用套路。但正如我们前面所说,通用思路存在一定的局限性——它提供给大家的毕竟是一种方向性的引导,至于能不能实实在在地用自己的双手解决掉一道具体的题目,更多还是看同学们自己的“造化”。

所谓“造化”,其实并不神秘,它就是指我们自己对题目和知识点的思考深度和吸收程度。“造化”是否到位,并不取决于天赋,而是取决于每一位同学自身对题目的量的积累和对解题技术的总结。

作为对通用解题套路的补充,本节笔者基于自己接触过的海量动态规划真题,结合个人对面试命题倾向的观察和思考,提取了两个学习性价比极高的重点解题模型。 模型可以帮助我们迅速地识别并解决掉一类问题,通过对重点模型进行学习,大家可以在实战中做到举一反N,大大提升我们做题的效率和专业程度。

# 0-1背包模型

30 秒速记

  • dp[c] 表示容量不超过 c 时的最大价值。
  • 每件物品只有选/不选两种;一维压缩后容量必须倒序,避免同一物品本轮重复使用。
  • 转移:dp[c] = max(dp[c], dp[c-weight] + value)。
  • 时间 O(nC)、空间 O(C);容量巨大时要考虑值域 DP 或其他算法。

0-1 背包用 dp[c] 表示容量不超过 c 时能取得的最大价值,每件物品只能选择一次或不选。 一维状态的转移是 dp[c] = max(dp[c], dp[c-weight] + value),它比较不放当前物品和放入当前物品两种结果。容量必须从大到小更新,因为正序会读到本轮刚写入的状态,让同一件物品被重复使用,问题就变成了完全背包。该做法时间复杂度为 O(nC)、空间复杂度为 O(C);如果容量特别大,还要考虑值域 DP 或其他算法。

回答参考:“0-1 的关键是每件只能用一次,所以一维 dp 倒序更新;若正序,同一物品的新状态会被本轮再次读取,悄悄变成完全背包。”

面试官追问

追问 1代码评审里有人把容量循环改成从小到大,声称 Math.max 会自动避免重复选择;用一个重量能被容量容纳多次的物品,结果会发生什么?
参考回答

结果可能在同一轮多次计入该物品,因为较大容量会读取本轮刚更新的 dp[c-weight]。Math.max 只比较候选价值,并不限制物品使用次数;这段代码的语义已经悄悄接近完全背包,违反每件物品只能选一次的约束。

追问 2商品组合页有数百件候选商品,前端只需计算容量上限内的最大价值,不展示具体清单;你会怎样落地 0-1 背包状态?
参考回答

可用长度为容量加一的一维 dp 数组,外层逐件遍历商品,内层容量从上限倒序到当前重量。这样每次转移仍读取上一轮语义的状态,并省去完整二维表;若之后要恢复商品清单,仅保留价值数组就不够,需要追加来源记录。

追问 3产品经理把规则改成同一种商品可选任意件,但开发仍坚持倒序容量更新;页面会漏掉哪类最优组合?
参考回答

倒序更新会让本轮无法复用刚写入的状态,因此同一商品仍最多贡献一次,可能漏掉重复选择该商品形成的更高价值组合。规则变成可重复选取后应改为正序容量更新;代价是模型语义变为完全背包,不能与原 0-1 约束混用。

追问 4线上组合结果异常偏大,日志显示只有一件重量为 2、价值为 3 的商品,容量为 6 时却得到 9;你会先查哪一层循环?
参考回答

先查容量循环是否从 2 正序走到 6,因为该顺序会依次读到本轮生成的 dp[2] 和 dp[4],把同一件商品累计三次。修复为从 6 倒序到 2,再用单物品用例回归;若商品本就允许重复,则异常来自需求模型选错。

0-1背包问题是一个基本问题,基于这个基本问题,可以衍生出千姿百态的变种问题,这种题目就非常适合拿来构造解题模型。

0-1背包问题说的是这么回事儿:

有 n 件物品,物品体积用一个名为 w 的数组存起来,物品的价值用一个名为 value 的数组存起来;每件物品的体积用 w[i] 来表示,每件物品的价值用 value[i] 来表示。现在有一个容量为 c 的背包,问你如何选取物品放入背包,才能使得背包内的物品总价值最大?

注意:每种物品都只有1件

# 思路分析

30 秒速记

  • 每件物品只能选一次,状态可定义为容量为 c 时前若干物品能取得的最大价值
  • 处理完第 i 件物品后,dp[c] 只代表前 i 件物品的最优解
  • 压成一维后容量必须从大到小遍历,否则本轮刚更新的状态会让同一物品被重复使用

这道题适合用动态规划,因为每件物品只有选和不选两种状态,而直接枚举会产生 2^n 种组合。 可以定义 dp[i][c] 为只看前 i 件物品、容量为 c 时的最大价值,再比较不选第 i 件的 dp[i-1][c],以及选它后的 dp[i-1][c-w[i]] + value[i]。由于当前行只依赖上一行,二维数组可以压缩成一维数组。压缩后容量必须倒序遍历,确保读取的仍是上一轮状态,避免当前物品在同一轮被重复选中。

← 动态规划入门

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • 前端算法面试

    • 数组基础
    • 栈、队列与链表
    • 树与二叉树
    • 二叉树递归遍历
    • 时间与空间复杂度
    • 数组高频题
    • 字符串高频题
    • 链表基础题
    • 链表双指针
    • 环形链表
    • 栈的经典应用
    • 队列与双端队列
    • DFS 与 BFS
    • 递归与回溯
    • 二叉树高频题
    • 二叉搜索树
    • 平衡二叉树
    • 堆与堆排序
    • 基础排序算法
    • 归并与快速排序
    • 动态规划入门
    • 动态规划进阶
      • 0-1背包模型
        • 思路分析
      • 最长上升子序列模型
        • 思路分析
        • 问题复盘