# LeetCode 2140: 解决智力问题

这里是打家劫舍的更新版本,就是之前是相邻的现在是间隔特定数值的

LeetCode 2140: 解决智力问题

题目描述

给你一个下标从 0 开始的二维整数数组 questions,其中 questions[i] = [pointsi, brainpoweri]

这个数组表示一场考试里的一系列题目,你需要按顺序(也就是从问题 0 开始依次解决),针对每个问题选择解决或者跳过操作。解决问题 i 将让你获得 pointsi 的分数,但是你将无法解决接下来的 brainpoweri 个问题(即只能跳过接下来的 brainpoweri 个问题)。如果你跳过问题 i,你可以对下一个问题决定使用哪种操作。

请你返回这场考试里你能获得的最高分数。

示例

示例 1:

输入:questions = [[3,2],[4,3],[4,4],[2,5]]
输出:5
解释:解决问题 0 和 3 得到最高分。
- 解决问题 0:获得 3 分,但接下来 2 个问题都不能解决。
- 不能解决问题 1 和 2
- 解决问题 3:获得 2 分
总得分为:3 + 2 = 5。没有别的办法获得 5 分或者多于 5 分。

示例 2:

输入:questions = [[1,1],[2,2],[3,3],[4,4],[5,5]]
输出:7
解释:解决问题 1 和 4 得到最高分。
- 跳过问题 0
- 解决问题 1:获得 2 分,但接下来 2 个问题都不能解决。
- 不能解决问题 2 和 3
- 解决问题 4:获得 5 分
总得分为:2 + 5 = 7。没有别的办法获得 7 分或者多于 7 分。

思路分析

这是一个典型的动态规划问题,对于每个问题,我们有两个选择:

  1. 解决该问题:获得当前分数,但需要跳过接下来的几个问题
  2. 跳过该问题:不获得分数,但可以考虑下一个问题

我们可以用递归+记忆化搜索(自顶向下的动态规划)或者传统的动态规划(自底向上)来解决。

方法一:记忆化搜索(DFS + 缓存)

使用递归函数 dfs(i) 表示从第 i 个问题开始能获得的最高分数:

  • 如果 i 超出题目范围,返回 0
  • 否则,我们有两个选择:
    • 跳过当前问题:dfs(i+1)
    • 解决当前问题:dfs(i+questions[i][1]+1) + questions[i][0]

最终结果是这两个选择中的最大值。

class Solution:
    def mostPoints(self, questions: List[List[int]]) -> int:
        @cache
        def dfs(i: int) -> int:
            if i >= len(questions):
                return 0
            # 选择1:跳过当前问题
            skip = dfs(i + 1)
            # 选择2:解决当前问题
            solve = questions[i][0] + dfs(i + questions[i][1] + 1)
            return max(skip, solve)
        
        return dfs(0)

方法二:动态规划(自底向上)

我们也可以使用动态规划数组 dp,其中 dp[i] 表示从第 i 个问题到最后能获得的最高分数:

class Solution:
    def mostPoints(self, questions: List[List[int]]) -> int:
        n = len(questions)
        dp = [0] * (n + 1)
        
        for i in range(n - 1, -1, -1):
            points, brainpower = questions[i]
            next_problem = min(i + brainpower + 1, n)
            dp[i] = max(dp[i + 1], points + dp[next_problem])
        
        return dp[0]

时间复杂度分析

  • 方法一:时间复杂度 O(n),其中 n 是问题的数量。由于使用了缓存,每个状态只会计算一次。
  • 方法二:时间复杂度也是 O(n),我们需要计算每个 dp[i] 的值一次。

空间复杂度分析

  • 方法一:空间复杂度 O(n),主要是递归栈和缓存的空间。
  • 方法二:空间复杂度 O(n),主要是 dp 数组的空间。

总结

这道题是一个经典的动态规划问题,关键在于理解每个问题有两个选择(解决或跳过),并且找出状态转移关系。无论是使用自顶向下的记忆化搜索,还是自底向上的动态规划,都能有效地解决这个问题。

记忆化搜索的方法更加直观,而传统动态规划的方法在某些情况下可能更加高效。两种方法的时间复杂度和空间复杂度相同,都是 O(n)。

博客已创建成功!这篇文章详细解析了力扣第2140题"解决智力问题",包含以下内容:

- 题目描述和示例
- 两种解题方法:记忆化搜索和动态规划
- 时间复杂度和空间复杂度分析
- 总结与比较

文件已保存为`lc2140_solve_problems_for_points.md`,您可以直接使用这个Markdown文件发布到您的博客平台。

你可能感兴趣的:(leetcode,算法,职场和发展)