[LeetCode108双周赛&LeetCode353周赛] 学习用记忆化搜索解决 DP 问题

这篇具有很好参考价值的文章主要介绍了[LeetCode108双周赛&LeetCode353周赛] 学习用记忆化搜索解决 DP 问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考灵神直播和代码

补充:DP 中常见的记忆化搜索 @cache 装饰器

@cache 装饰器的作用:将传入不同参数得到的函数值存储到缓存,避免下次传递相同参数重复计算结果,可用于解决递归函数重复计算问题,比如递归求斐波那契问题。

6899. 达到末尾下标所需的最大跳跃次数

https://leetcode.cn/problems/maximum-number-of-jumps-to-reach-the-last-index/

Solution

记忆化搜索

dfs(i) 表示以 nums[i] 为终点求的最大跳跃数

class Solution:
    def maximumJumps(self, nums: List[int], target: int) -> int:
        n = len(nums)
        @cache
        def dfs(i :int) -> int:
            if i == 0:
                return 0
            res = -inf
            for j in range(i):
                if abs(nums[i] - nums[j]) <= target:
                    res = max(res, dfs(j) + 1)
            return res
        ans = dfs(n-1)
        return ans if ans > 0 else -1

递推(逆向)

dp(i) 表示以 nums[i] 为终点求的最大跳跃数

class Solution:
    def maximumJumps(self, nums: List[int], target: int) -> int:
        n = len(nums)
        dp = [-inf] * n
        dp[0] = 0
        for i in range(1, n):
            for j in range(i):
                if abs(nums[i] - nums[j]) <= target:
                    dp[i] = max(dp[i], dp[j] + 1)
        return dp[-1] if dp[-1] > 0 else -1

递推(正向)

class Solution:
    def maximumJumps(self, nums: List[int], target: int) -> int:
        n = len(nums)   
        dp = [-1] * n
        dp[0] = 0
        for i in range(n):
            if dp[i] >= 0: # 关键判断
                for j in range(i + 1, n):
                    if abs(nums[j] - nums[i]) <= target:
                        dp[j] = max(dp[j], dp[i] + 1)
        return dp[-1]

6912. 构造最长非递减子数组

https://leetcode.cn/problems/longest-non-decreasing-subarray-from-two-arrays/

Solution

记忆化搜索

dfs(i, 0/1) 表示以 nums1[i] 或者 nums2[i] 结尾的最大

class Solution:
    def maxNonDecreasingLength(self, nums1: List[int], nums2: List[int]) -> int:
        nums = (nums1, nums2)
        @cache
        def dfs(i: int, j: int) -> int:
            if i == 0:
                return 1
            res = 1
            # 如果 nums1[i-1] 符合条件
            if nums1[i-1] <= nums[j][i]:
                res = max(res, dfs(i - 1, 0) + 1)
            # 如果 nums2[i-1] 符合条件
            if nums2[i-1] <= nums[j][i]:
                res = max(res, dfs(i - 1, 1) + 1)
            return res
        ans = 0
        for i in range(len(nums1)):
            ans = max(ans, dfs(i, 0), dfs(i, 1))
        return ans

6919. 使数组中的所有元素都等于零

https://leetcode.cn/problems/apply-operations-to-make-all-array-elements-equal-to-zero/

Solution

差分数组

差分数组求前缀和即为各个区间的最终变化结果,差分数组可以把一个区间操作变为对两个数的操作,从而节省时间。

class Solution:
    def checkArray(self, nums: List[int], k: int) -> bool:
        n = len(nums)
        d = [0] * (n + 1) # 差分数组
        pre = 0 # 记录差分数组的前缀和, 边扫描, 边计算

        for i, x in enumerate(nums):
            pre += d[i]
            x += pre
            if x == 0:
                continue
            # x < 0 表示已经减到了负数, 不符合要求
            # i + k > 0 表示越界了, 不符合要求
            if x < 0 or i + k > n:
                return False
            # 差分过程
            pre -= x
            d[i+k] += x
        return True

6923. 将字符串分割为最少的美丽子字符串

https://leetcode.cn/problems/partition-string-into-minimum-beautiful-substrings/description/

相关题目

131. 分割回文串

Solution

记忆化搜索

dfs(i) 表示从 s[i]s[n-1] 最少分割成多少段文章来源地址https://www.toymoban.com/news/detail-542288.html

class Solution:
    def minimumBeautifulSubstrings(self, s: str) -> int:
        pow5 = [bin(5**i)[2:] for i in range(10) if len(bin(5**i)[2:]) <= 15]
        n = len(s)
        @cache
        def dfs(i :int) -> int:
            if i == n:
                return 0
            if s[i] == '0': # 表示不合法的状态
                return inf 

            res = inf

            # 遍历 5 的幂二进制串, 看选哪一个
            for t in pow5:
                if i + len(t) > n:
                    break
                if s[i:i + len(t)] == t:
                    res = min(res, dfs(i + len(t)) + 1)
            return res
        ans = dfs(0)
        return ans if ans < inf else -1


到了这里,关于[LeetCode108双周赛&LeetCode353周赛] 学习用记忆化搜索解决 DP 问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第 107 场LeetCode双周赛

    A 最大字符串配对数目 显然各字符串对 间匹配的先后顺序不影响最大匹配数目, 可以从后往前遍历数组, 判断前面是否有和当前末尾构成匹配的. B 构造最长的新字符串 记忆化搜索: 定义状态 p a a , b b , a b , l a s t p_{aa,bb,ab,last} p aa , bb , ab , l a s t ​ 为剩余三种字符串分别为aa、

    2024年02月11日
    浏览(44)
  • leetcode第124场双周赛

    给你一个整数数组  nums  ,如果  nums   至少  包含  2  个元素,你可以执行以下操作: 选择  nums  中的前两个元素并将它们删除。 一次操作的  分数  是被删除元素的和。 在确保  所有操作分数相同  的前提下,请你求出  最多  能进行多少次操作。 请你返回按照上述

    2024年02月19日
    浏览(41)
  • leetcode 122双周赛 解题思路+代码

    本人水平有限,只做出3道,最后1道放弃。 给你一个长度为 n 的整数数组 nums 。 一个数组的 代价 是它的 第一个 元素。比方说,[1,2,3] 的代价是 1 ,[3,4,1] 的代价是 3 。 你需要将 nums 分成 3 个 连续且没有交集 的子数组。 请你返回这些子数组的 最小 代价 总和 。 示例 1: 输

    2024年02月20日
    浏览(43)
  • LeetCode---121双周赛---数位dp

    2996. 大于等于顺序前缀和的最小缺失整数 2997. 使数组异或和等于 K 的最少操作次数 2998. 使 X 和 Y 相等的最少操作次数 2999. 统计强大整数的数目 简单的模拟题,只要按照题目的要求去写代码即可,代码如下 这题考异或的性质---相同为0,相异为1,我们只要关心nums的异或和与

    2024年01月22日
    浏览(56)
  • 第 122 场 LeetCode 双周赛题解

    A 将数组分成最小总代价的子数组 I 枚举:枚举后两个子数组的起始下标 B 判断一个数组是否可以变为有序 模拟:模拟冒泡排序的过程,若相邻元素大小关系需要交换位置,但其二进制下数位为 1 的数目不同,则返回false,若完成排序返回true C 通过操作使数组长度最小 脑筋急

    2024年01月22日
    浏览(42)
  • LeetCode 双周赛 106(2023/06/10)两道思维题

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 加入知识星球提问。 往期回顾:LeetCode 单周赛第 348 场 · 数位 DP 模版学会了吗? T1. 判断一个数是否迷人(Easy) 标签:计数 T2. 找到最长的半重复子字符串(Medium) 标签:同向双指针 T3. 移动机器人(Medi

    2024年02月08日
    浏览(41)
  • LeetCode 双周赛 103(2023/04/29)区间求和的树状数组经典应用

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 大家好,我是小彭。 这场周赛是 LeetCode 双周赛第 103 场,难得在五一假期第一天打周赛的人数也没有少太多。这场比赛前 3 题比较简单,我们把篇幅留给最后一题。 往期周赛回顾:LeetCode 单周赛第

    2024年02月02日
    浏览(65)
  • LeetCode 双周赛 101,DP/中心位贪心/裴蜀定理/Dijkstra/最小环

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 大家好,我是小彭。 这周比较忙,上周末的双周赛题解现在才更新,虽迟但到哈。上周末这场是 LeetCode 第 101 场双周赛,整体有点难度,第 3 题似乎比第 4 题还难一些。 2605. 从两个数字数组里生成最

    2023年04月09日
    浏览(46)
  • LeetCode 双周赛 104(2023/05/13)流水的动态规划,铁打的结构化思考

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 往期回顾:LeetCode 单周赛第 344 场 · 手写递归函数的通用套路 T1. 老人的数目(Easy) 标签:模拟、计数 T2. 矩阵中的和(Medium) 标签:模拟、排序 T3. 最大或值(Medium) 标签:动态规划、前后缀分解

    2024年02月04日
    浏览(58)
  • 周赛379(排序、分类讨论、记忆化搜索(动态规划))

    简单 给你一个下标从 0 开始的二维整数数组 dimensions 。 对于所有下标 i ( 0 = i dimensions.length ), dimensions[i][0] 表示矩形 i 的长度,而 dimensions[i][1] 表示矩形 i 的宽度。 返回对角线最 长 的矩形的 面积 。如果存在多个对角线长度相同的矩形,返回面积最 大 的矩形的面积。

    2024年01月19日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包