力扣每日一题 6/14 动态规划+数组

简介: 力扣每日一题 6/14 动态规划+数组

2786.访问数组中的位置使分数最大【中等

题目:

给你一个下标从 0 开始的整数数组 nums 和一个正整数 x

一开始 在数组的位置 0 处,你可以按照下述规则访问数组中的其他位置:

  • 如果你当前在位置 i ,那么你可以移动到满足 i < j任意 位置 j
  • 对于你访问的位置 i ,你可以获得分数 nums[i]
  • 如果你从位置 i 移动到位置 jnums[i]nums[j]奇偶性 不同,那么你将失去分数 x

请你返回你能得到的 最大 得分之和。

注意 ,你一开始的分数为 nums[0]

示例 1:

输入:nums = [2,3,6,1,9,2], x = 5

输出:13

解释:我们可以按顺序访问数组中的位置:0 -> 2 -> 3 -> 4 。

对应位置的值为 2 ,6 ,1 和 9 。因为 6 和 1 的奇偶性不同,所以下标从 2 -> 3 让你失去 x = 5 分。

总得分为:2 + 6 + 1 + 9 - 5 = 13 。


示例 2:

输入:nums = [2,4,6,8], x = 3

输出:20

解释:数组中的所有元素奇偶性都一样,所以我们可以将每个元素都访问一次,而且不会失去任何分数。

总得分为:2 + 4 + 6 + 8 = 20 。


提示:

  • 2 <= nums.length <= 10**5
  • 1 <= nums[i], x <= 10**6

分析问题:

  • 这是一个动态规划问题,需要考虑在每个位置上能获得的最大得分。
  • 关键在于判断移动到下一个位置时是否会因为奇偶性不同而失去分数 x,并在此基础上计算最大得分。

解题方案

  1. 定义一个二维数组 dp[i][0]dp[i][1] ,分别表示在位置 i 且当前数字为奇数或偶数时能获得的最大得分。
  2. 初始化 dp[0][0] = nums[0] (如果 nums[0] 为偶数),dp[0][1] = nums[0] (如果 nums[0] 为奇数)。
  3. 从位置 1 开始遍历数组 nums
  • 如果 nums[i] 为偶数:
  • dp[i][0] = max(dp[i - 1][0] + nums[i], dp[i - 1][1] + nums[i] - x)
  • dp[i][1] = dp[i - 1][1]
  • 如果 nums[i] 为奇数:
  • dp[i][1] = max(dp[i - 1][1] + nums[i], dp[i - 1][0] + nums[i] - x)
  • dp[i][0] = dp[i - 1][0]
  1. 最终的最大得分即为 max(dp[n - 1][0], dp[n - 1][1]) ,其中 n 是数组 nums 的长度。

代码实现:

from functools import cache
class Solution:
    def maxScore(self, nums: List[int], x: int) -> int:
        @cache
        def dfs(i,j):
            if i == len(nums): return 0
            if nums[i] % 2 != j: return dfs(i+1,j)
            return max(dfs(i+1,j),dfs(i+1,j^1)-x)+nums[i]
        return dfs(0,nums[0]%2)

总结:

          利用 functools 模块中的 cache 装饰器对 dfs 函数进行缓存优化,避免重复计算。

   dfs 函数接受两个参数 ij ,分别表示当前在数组 nums 中的位置和当前数字的奇偶性标志(0 表示偶数,1 表示奇数)。

       函数首先判断如果当前位置 i 达到数组末尾,返回 0 。

       如果当前数字的奇偶性与 j 不一致,直接返回下一个位置且奇偶性不变时的结果,即 dfs(i + 1, j)

       否则,返回两种可能情况中的最大值:一是直接移动到下一个位置且奇偶性不变时的结果 dfs(i + 1, j) ,二是移动到下一个位置且奇偶性改变时减去 x 再加上当前数字 nums[i] 的结果 dfs(i + 1, j ^ 1) - x + nums[i]

       最终,通过调用 dfs(0, nums[0] % 2) 来计算并返回最大得分。


这道题考察的内容包括

  1. 对动态规划思想的理解和应用,需要找到最优的决策路径来获得最大得分。
  2. 对函数递归调用的掌握,通过递归的方式遍历所有可能的移动情况。
  3. 对奇偶性判断和处理的能力,根据数字的奇偶性做出不同的决策。
  4. 对缓存装饰器的运用,优化函数的性能,避免重复计算。

从这道题中可以学到

  1. 深入理解动态规划的解题思路,学会如何定义状态和状态转移方程来解决最优解问题。
  • 例如,通过定义 dp[i][0]dp[i][1] 来表示不同奇偶性下的最大得分。
  1. 掌握递归函数的设计和编写,清晰地定义递归的终止条件和递归逻辑。
  • 像本题中的 dfs 函数,通过递归探索所有可能的位置移动情况。
  1. 提升对数字奇偶性的处理能力,灵活运用奇偶性来制定策略。
  • 依据数字的奇偶性决定是否扣除分数 x
  1. 认识到缓存装饰器的作用和优势,学会在适当的场景中运用缓存来提高程序的效率。
  • 利用 @cache 避免重复计算相同参数的 dfs 结果。

“所谓宿命,其实都是最好的安排。”——《将夜》

目录
打赏
0
1
1
0
37
分享
相关文章
|
1月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
52 1
【LeetCode 热题100】139:单词拆分(动态规划全解析+细节陷阱)(Go语言版)
本题是 LeetCode 热题 139:单词拆分(Word Break),需判断字符串 `s` 是否能由字典 `wordDict` 中的单词拼接而成。通过动态规划(DP)或记忆化搜索解决。DP 中定义布尔数组 `dp[i]` 表示前 `i` 个字符是否可拆分,状态转移方程为:若存在 `j` 使 `dp[j]=true` 且 `s[j:i]` 在字典中,则 `dp[i]=true`。初始条件 `dp[0]=true`。代码实现中用哈希集合优化查找效率。记忆化搜索则从起始位置递归尝试所有切割点。两种方法各有利弊,DP 更适合面试场景。思考扩展包括输出所有拆分方式及使用 Trie 优化大字典查找。
85 6
|
9月前
|
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
92 0
|
11月前
|
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
9月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
60 4
|
9月前
|
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
72 0
Leetcode第三十三题(搜索旋转排序数组)
|
11月前
|
LeetCode第81题搜索旋转排序数组 II
文章讲解了LeetCode第81题"搜索旋转排序数组 II"的解法,通过二分查找算法并加入去重逻辑来解决在旋转且含有重复元素的数组中搜索特定值的问题。
LeetCode第81题搜索旋转排序数组 II
|
9月前
|
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
149 0
|
9月前
|
C++
【LeetCode 12】349.两个数组的交集
【LeetCode 12】349.两个数组的交集
57 0
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
这篇文章介绍了LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"的解题方法,通过使用双指针法从数组两端向中间同时查找目标值,有效地找到了目标值的首次和最后一次出现的索引位置。
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问