dp[i][j]
代表针对arr1[i]
,选择数字j
的情况下,单调数组对数.
因为nums[i]
最大只有50
,暴力选择每一个j
class Solution:
def countOfPairs(self, nums: List[int]) -> int:
MOD = 10 ** 9 + 7
n = len(nums)
dp = [[0] * (nums[i] + 1) for i in range(n)]
# 初始化第一个位置
for j in range(nums[0] + 1):
dp[0][j] = 1
# 动态规划填表
for i in range(1, n):
for j in range(nums[i] + 1):
x = nums[i] - j
for pre_j in range(j + 1):
pre_x = nums[i-1] - pre_j]
if pre_x >= x :
dp[i][j] += dp[i-1][pre_j]
else:break
dp[i][j] %= MOD
# 结果求和
result = sum(dp[n - 1]) % MOD
return result
单调数组对的数目2
当nums[i]
提高到1000
,就不能暴力了
观察T1
代码发现,第三重循环是单调的,找到所有pre_j
,然后比对pre_x >= x
,不满足就退出。我们可以设计算法,O(1)
复杂度找出最合适的pre_j
,也就是所有满足pre_j
的和,需要用前缀和来优化
dp[i][j]
代表针对arr1[i]
选择所有小于等于j
的数字所形成的单调数对
class Solution:
def countOfPairs(self, nums: List[int]) -> int:
MOD = 10 ** 9 + 7
n = len(nums)
dp = [[0] * (nums[i] + 1) for i in range(n)]
# 初始化第一个位置
for j in range(nums[0] + 1):
dp[0][j] = j + 1
# 动态规划填表
for i in range(1, n):
for j in range(nums[i] + 1):
x = nums[i] - j # x肯定大于0
pre_j = nums[i-1] - x # 上一个能选的最大的j
pre_j = min(pre_j, j) # 有可能pre_j更大,题目规定arr1非递减
if pre_j < 0:tmp = 0 # 有可能没有pre_j,那么我们也要处理前缀和
else: tmp = dp[i-1][pre_j]
if j != 0:
dp[i][j] = tmp + dp[i][j-1]
else: dp[i][j] = tmp
dp[i][j] %= MOD
# 结果求和
result = dp[n - 1][nums[-1]] % MOD
return result