算法学习(十四)

学习内容:

动态规划算法:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
在查找有很多重叠子问题的情况的最优解有效。动态规划保存子问题的解,避免重复计算。

学习产出:

分割类题型

动态规划

解决动态规划问题的关键是找到状态转移方程,这样就可以通过计算和存储子问题的解来解决最终问题。

LeetCode 279 完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:

输入:n = 12
输出:3 
解释:12 = 4 + 4 + 4
         
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-squares
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

状态转移方程不依赖于相邻位置,而是依赖于满足分割条件位置。定义一个以为矩阵dp[i],其中i表示数字,dp[i]表示数字i最少可以由几个完全平方的数相加构成。因此状态转移方程dp[i]=1+min(dp[i-1],dp[i-4],…)

代码(python)

class Solution:
    def numSquares(self, n: int) -> int:
        dp = [0]*(n+1)
        for i in range(1,n+1):
            dp[i] =i
            j=1
            while i-j*j>=0:
                dp[i] = min(dp[i],dp[i-j*j]+1)
                j+=1
        return dp[n]
        			

LeetCode 91 解码方法

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“111” 可以将 “1” 中的每个 “1” 映射为 “A” ,从而得到 “AAA” ,或者可以将 “11” 和 “1”(分别为 “K” 和 “A” )映射为 “KA” 。注意,“06” 不能映射为 “F” ,因为 “6” 和 “06” 不同。

给你一个只含数字的 非空 字符串 num ,请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。

示例 1:

输入:s = "12"
输出:2
解释:它可以解码为 "AB"1 2)或者 "L"12)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-ways
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    

题解

dp[i]表示以i为结尾的可能编码数,两种可能,一种是本身作为一个编码,如果符合条件那么dp[i] = dp[i - 1],另外一种是前一个数字和本身构成编码,如果符合条件那么dp[i] = dp[i - 2],这里如果i-2越界了那么就是dp[i] = 1

代码(python)

class Solution:
    def numDecodings(self, s: str) -> int:
        length = len(s)
        dp = [0] * length
        dp[0] = 0 if s[0] == '0' else 1
        for i in range(1, length):
            if s[i] != '0':
                t1 = dp[i - 1]
            else:
                t1 = 0
            if i - 2 >= 0:
                t2 = dp[i - 2]
            else:
                t2 = 0
            if int(s[i - 1: i + 1]) <= 26 and s[i - 1: i + 1][0] != '0':
                t3 = True
            else:
                t3 = False
            if t3:
                dp[i] = t1 +t2
            else:
                dp[i] = t1
            if i - 2 < 0 and t3:
                dp[i] += 1
        return dp[-1]
        

LeetCode 139 单词拆分

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    

题解

与完全平方数分割类似,考虑每个分割位置时需要遍历字符串集合,以确定当前位置是否可以成功分割

代码(python)

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        length = len(s)
        a = s
        dp = [False]*(length+1)
        dp[0] = True
        for i in range(1,length+1):
            for word in wordDict:
                wordlength = len(word)
                if i >= wordlength and s[i-wordlength:i] == word:
                    dp[i] = dp[i] or dp[i-wordlength]
        return dp[length]
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值