刷题-动态规划

打家劫舍

获得不相邻的元素最大和
输入:[1,2,3,1]
输出:4

class Solution:
    def rob(self, nums: List[int]) -> int:
        lens = len(nums)  # 获取输入列表的长度
        if lens <= 2:  # 如果长度小于等于2
            return max(nums)  # 返回列表中的最大值
        before1 = nums[0]  # 初始化 before1 为第一个元素的值
        before2 = max(before1, nums[1])  # 初始化 before2 为前两个元素中的最大值
        for i in range(2, lens):  # 从第三个元素开始迭代
            now = max(before2, before1 + nums[i])  # 计算当前最大值,要么不抢当前房子,要么抢当前房子
            before1 = before2  # 更新 before1 为上一次的 before2
            before2 = now  # 更新 before2 为当前的最大值
        return now  # 返回计算出的最大值

完全平方数

class Solution:
    def numSquares(self, n: int) -> int:
        dp = [i for i in range(n+1)]  # 初始化 dp 数组,dp[i] 表示 i 最少可以由多少个完全平方数之和组成
        squares = [i*i for i in range(1, int(n**0.5)+1)]  # 预先计算所有小于等于 n 的完全平方数
        for i in range(4, n+1):  # 从 4 开始遍历到 n
            for j in squares:  # 遍历所有的完全平方数
                if j > i:  # 如果完全平方数大于当前的 i
                    continue  # 跳过后续的计算
                dp[i] = min(dp[i], dp[i-j]+1)  # 更新 dp[i] 为使用当前完全平方数 j 和之前的 dp[i-j] 的最小值
        return dp[n]  # 返回 dp[n],即 n 最少可以由多少个完全平方数之和组成

零钱兑换

计算并返回可以凑成总金额所需的 最少的硬币个数 。

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [float('inf') for i in range(amount+1)]  # 初始化 dp 数组,dp[i] 表示组成金额 i 所需的最少硬币数
        dp[0] = 0  # 组成金额 0 所需硬币数为 0
        for i in coins[::-1]:  # 逆序遍历硬币列表
            for j in range(i, amount+1):  # 从当前硬币金额 i 到目标金额 amount 遍历
                dp[j] = min(dp[j], dp[j-i] + 1)  # 更新 dp[j] 为使用当前硬币 i 时的最小值
            # print(i, dp)  # 如果需要,可以打印中间状态以调试
        return dp[amount] if dp[amount] != float('inf') else -1  # 如果无法组成目标金额,返回 -1

单次拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        n = len(s)  # 获取字符串 s 的长度
        dp = [False for i in range(n+1)]  # 初始化 dp 数组,dp[i] 表示 s 的前 i 个字符是否可以被拆分成字典中的单词
        dp[0] = True  # 空字符串可以被拆分
        for i in range(n):  # 遍历字符串的每个字符
            for j in range(i+1, n+1):  # 从 i+1 到 n 遍历
                if dp[i] and s[i:j] in wordDict:  # 如果 dp[i] 为 True 且子串 s[i:j] 在字典中
                    dp[j] = True  # 更新 dp[j] 为 True,表示前 j 个字符可以被拆分
        return dp[-1]  # 返回 dp[n],即整个字符串 s 是否可以被拆分成字典中的单词

最长递增子序列

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        dp = [1] * len(nums)  # 初始化 dp 数组,每个元素初始化为 1,表示以当前元素为结尾的最长递增子序列长度至少为 1
        
        for i in range(len(nums)):  # 遍历数组的每一个元素
            for j in range(0, i):  # 遍历当前元素之前的所有元素
                if nums[j] < nums[i]:  # 如果前面的元素小于当前元素
                    dp[i] = max(dp[j] + 1, dp[i])  # 则更新 dp[i],为 dp[j] + 1 和 dp[i] 之间的最大值
                    
        return max(dp)  # 返回 dp 数组中的最大值,即最长递增子序列的长度

乘积最大子数组

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        final_max = float('-inf')  # 初始化最终最大值为负无穷大
        fmin, fmax = 1, 1  # 初始化当前最小值和最大值为 1
        
        for i in nums:  # 遍历数组的每一个元素
            if i < 0:  # 如果当前元素小于 0
                fmin, fmax = fmax, fmin  # 交换当前最小值和最大值,因为乘以负数会逆转最大最小
            
            fmax = max(fmax * i, i)  # 更新当前最大值为当前元素或当前元素乘以之前的最大值
            fmin = min(fmin * i, i)  # 更新当前最小值为当前元素或当前元素乘以之前的最小值
            final_max = max(fmax, final_max)  # 更新最终最大值
            
        return final_max  # 返回最终最大值

分割等和子集

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        s = sum(nums)  # 计算数组 nums 的总和
        if s % 2:  # 如果总和是奇数,无法平分
            return False  # 返回 False
        s //= 2  # 将总和减半,目标是找出部分和为 s 的子集
        n = len(nums)  # 获取数组的长度
        f = [[False] * (s + 1) for _ in range(n + 1)]  # 初始化二维数组 f,大小为 (n+1) x (s+1)
        f[0][0] = True  # 初始状态,用空集合达到和为 0
        for i, x in enumerate(nums):  # 枚举数组中的每一个数
            for j in range(s + 1):  # 枚举每一个可能的和
                f[i + 1][j] = j >= x and f[i][j - x] or f[i][j]  # 更新状态,f[i][j] 表示用 nums[:i] 能达到和为 j
        print(f[-1])  # 打印最后一行状态,用于调试
        return f[n][s]  # 返回是否能够找到一个子集,其和为 s

最长有效括号

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        stack = []  # 栈用于存储索引
        res = 0  # 存储最长有效括号长度
        if not s:  # 如果字符串为空
            return 0  # 返回 0
        for index, i in enumerate(s):  # 遍历字符串中的每一个字符及其索引
            if not stack or i == '(' or s[stack[-1]] == ')':  # 如果栈为空,或者当前字符为 '(',或者栈顶对应的字符为 ')'
                stack.append(index)  # 将当前索引压入栈中
            else:  # 如果当前字符为 ')'
                stack.pop()  # 弹出栈顶元素
                res = max(res, index - (stack[-1] if stack else -1))  # 更新最长有效括号长度
        return res  # 返回最长有效括号长度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值