[算法数据结构] 动态规划再总结

94 阅读2分钟

在总结之后,做了完全平方数和单词拆分问题。结束了完全背包章节的学习,同时也完成了背包问题的全部题目。其中,完全平方数完全是自己想出来的,单词拆分没有想出来怎么做。下面思考其中的异同。

  • 完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

可以将正整数n抽象为背包的容量,然后待选的物品是1平方,2平方,...注意可以无限次的用,因此这是完全背包问题,注意在遍历背包的时候,从物品的大小开始选。dp[i]的含义是和为i的完全平方数的最少数量。背包和物品的遍历的先后顺序有什么影响呢? 注意和求组合排列的方法总数不同,求组合或者排列总数的话,dp[i] += dp[i - nums[j]]。 这里的要用的递推公式是:dp[i] = min(dp[i - j * j] + 1, dp[i])。根本影响在于dp[i]的含义不同。前者是凑成目标正整数为i的排列个数,后者是和为j的完全平方数的最少数量为dp[j]。一个排列个数,一个是所有排列中最少个数数量。所以对于后者而言,无论是排列还是组合都不会影响答案。

  • 单词拆分

单词拆分,可以认为给的字符串是背包,物品是字典,并且物品可以重复用,因此这是完全背包问题。难点在与和字符串关联在一起,怎么处理?dp[i] 字符串长度为i的话,dp[i]为true, 表示可以拆分为一个或多个在字典中出现的单词。主要是如何遍历背包和物品。遍历背包直接遍历字符串,遍历物品的思路就是在字符串中不断截取i-j,判断s.substr(j, i-j) 是否在字典中。这也是为什么将遍历背包放在外层循环中。