更弱智的算法学习day 38

322. 零钱兑换

dp[i]代表什么:

对于给定整数i,能凑成总金额所需的最少硬币的个数为dp[i]个

状态转移方程:

dp[i] = min(dp[i-j] + 1 , dp[i] )

也即选和不选两种情况,不选就是dp[i],选了就是dp[i-j]+1(多加一枚i硬币)

初始化:

由于要选最小,其他都初始化成inf,dp[0]初始化为0,想凑成amount只有0种方法

遍历顺序:

由于是组合,且是完全背包

组合先便利物品再遍历背包;排列先便利背包再遍历物品

01背包遍历背包时需要倒序;完全背包正序

故先正向遍历硬币,再正向遍历amount

python 复制代码
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [inf] * (amount + 1)

        dp[0] = 0
        for j in coins:
            for i in range(j, amount+1):
                    dp[i] = min(dp[i-j] + 1 , dp[i] )

        if dp[amount] == inf:
            return -1
        
        return dp[amount]

279.完全平方数

dp[i]代表什么:

对于给定整数i,能凑成和为n的所需的完全平方数的最小个数为dp[i]个

状态转移方程:

dp[i] = min(dp[i-j] + 1 , dp[i] )

也即选和不选两种情况,不选就是dp[i],选了就是dp[i-j]+1(多加一个i*i完全平方数)

初始化:

由于要选最小,其他都初始化成inf,dp[0]初始化为0,想凑成n只有0种方法

遍历顺序:

由于是组合,且是完全背包

组合先便利物品再遍历背包;排列先便利背包再遍历物品

01背包遍历背包时需要倒序;完全背包正序

故先正向遍历完全平方数,再正向遍历n

其中:

  • 1 <= n <= 10**4
  • 故i范围在0-100即可
python 复制代码
class Solution:
    def numSquares(self, n: int) -> int:
        dp = [inf] * (n+1)

        dp[0] = 0

        for i in range(101):
            for j in range(i*i, n+1):
                dp[j] = min(dp[j], dp[j-i*i]+1)

        return dp[n] 

139.单词拆分

该题略微复杂,需要进行匹配验证,仔细理解一下

dp[i]代表什么:

对于给定字符串s,考虑其前i位长度的字符能否被worddict列表中的字符串加和表示的布尔数组

状态转移方程:

我的理解是,对于没有加入字符串worddict【j】的dp【i-len【j】】而言:

首先要满足dp【i-len【j】】能被worddict列表中的字符串加和表示,也即==True

其次要满足加上字符串j之后,和dp【i】相同,也即:实际上是把worddict【j】长度的s字符串的内容切下来和真正的worddict【j】比较

s[i-len(wordDict[j]) : i]==wordDict[j]

初始化:

由于是布尔数组,初始化都初始化False,但考虑dp[0]如果为False,无法正常推进,因为dp[s]全是False,所以dp[0]==True

遍历顺序:

由于是排列,且是完全背包

组合先便利物品再遍历背包;排列先便利背包再遍历物品

01背包遍历背包时需要倒序;完全背包正序

故先正向遍历s的长度,再正向遍历worddict

python 复制代码
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        dp = [False] * (len(s) + 1)

        dp[0] = True

        for i in range(len(s)+1):
            for j in range(len(wordDict)):
                if len(wordDict[j]) <= i:
                    if dp[i-len(wordDict[j])] == True and s[i-len(wordDict[j]) : i]==wordDict[j]  :
                        dp[i] = True
                        break

                    
        return dp[len(s)]

关于多重背包,你该了解这些!

区别主要体现在下面这里,还需要遍历背包种某物品的可能选择数量k

python 复制代码
# 01背包的状态转移(单一选择)
dp[j] = max(dp[j], dp[j - weight] + value)

# 多重背包的状态转移(多重选择)
for k in range(1, nums[i] + 1):  # 需要遍历所有可能的选择数量
    if k * weight <= j:
        dp[j] = max(dp[j], dp[j - k*weight] + k*value)
相关推荐
惜.己2 小时前
使用python复制目录以及目录的子目录的文件到脚本运行的目录(工具+源码)
python
nvd112 小时前
Python 连接 MCP Server 全指南
开发语言·python
秦奈2 小时前
Unity复习学习笔记(八):动画、模型与寻路
笔记·学习·unity
电商API&Tina2 小时前
合规电商数据采集 API|多平台实时数据抓取,告别爬虫封号风险
大数据·开发语言·前端·数据库·爬虫·python
brave and determined2 小时前
工程设计类学习(DAY6):PCB可制造性设计规范全解析
网络·嵌入式硬件·学习·pcb设计·设计规范·嵌入式设计·设计工艺
天才测试猿2 小时前
自动化测试用例编写
自动化测试·软件测试·python·测试工具·程序人生·职场和发展·测试用例
忘忧记2 小时前
基于Tkinter基础模板的开发流程指南
开发语言·python
姚瑞南2 小时前
【AI 风向标】强化学习(RL):智能体自我优化的学习范式
人工智能·经验分享·python·gpt·深度学习·学习·机器学习
kitsch0x972 小时前
论文学习_Grey-Box Concolic Testing on Binary Code
学习