原理

当 DP 转移方程是如下形式时

$$ \begin{align} dp[i]=f(\sum_{J=a}^{b}dp[j]) & (0 \leq a \leq b < i) \end{align} $$

计算 dp[j] 需要先计算 $sum(dp[a...b])$,如果每次都遍历,每次遍历的时间复杂度为 $O(N)$,总体时间复杂度为 $O(N^2)$。

如果在状态转移过程中维护一个 dp 数组的前缀和数组 sums,则可以以空间换时间,每次遍历的时间复杂度为 $O(1)$,总体时间复杂度为 $O(N)$。

例题

1871. 跳跃游戏 VII

给你一个下标从 0 开始的二进制字符串 s 和两个整数 minJumpmaxJump 。一开始,你在下标 0 处,且该位置的值一定为 '0' 。当同时满足如下条件时,你可以从下标 i 移动到下标 j 处:

  • i + minJump <= j <= min(i + maxJump, s.length - 1)
  • s[j] == '0'.

如果你可以到达 s 的下标 s.length - 1 处,请你返回 true ,否则返回 false

class Solution {
    public boolean canReach(String s, int minJump, int maxJump) {
        int length = s.length();
        boolean[] dp = new boolean[length];
        int[] pre = new int[length + 1];
        dp[0] = true;
        for (int i = 1; i < minJump + 1; i++) {
            pre[i] = 1;
        }
        for (int i = minJump; i < length; i++) {
            int left = i - maxJump;
            int right = i - minJump;
            if (s.charAt(i) == '0' && pre[right + 1] - (left >= 0 ? pre[left] : 0) > 0) {
                dp[i] = true;
                pre[i + 1] = pre[i] + 1;
            } else {
                pre[i + 1] = pre[i];
            }
        }
        return dp[length - 1];
    }
}
最后修改:2024 年 10 月 31 日
如果觉得我的文章对你有用,请随意赞赏