class Solution {
public:
int countOfPairs(vector<int>& nums) {
}
};
100395. 单调数组对的数目 I
给你一个长度为 n
的 正 整数数组 nums
。
如果两个 非负 整数数组 (arr1, arr2)
满足以下条件,我们称它们是 单调 数组对:
n
。arr1
是单调 非递减 的,换句话说 arr1[0] <= arr1[1] <= ... <= arr1[n - 1]
。arr2
是单调 非递增 的,换句话说 arr2[0] >= arr2[1] >= ... >= arr2[n - 1]
。0 <= i <= n - 1
都有 arr1[i] + arr2[i] == nums[i]
。请你返回所有 单调 数组对的数目。
由于答案可能很大,请你将它对 109 + 7
取余 后返回。
示例 1:
输入:nums = [2,3,2]
输出:4
解释:
单调数组对包括:
([0, 1, 1], [2, 2, 1])
([0, 1, 2], [2, 2, 0])
([0, 2, 2], [2, 1, 0])
([1, 2, 2], [1, 1, 0])
示例 2:
输入:nums = [5,5,5,5]
输出:126
提示:
1 <= n == nums.length <= 2000
1 <= nums[i] <= 50
相似题目
原站题解
rust 解法, 执行用时: 4 ms, 内存消耗: 2.5 MB, 提交时间: 2024-11-28 09:07:22
impl Solution { pub fn count_of_pairs1(nums: Vec<i32>) -> i32 { let n = nums.len(); let mut dp = vec![vec![0; 51]; n]; let modulo = 1000000007; for v in 0..=nums[0] { dp[0][v as usize] = 1; } for i in 1..n { for v2 in 0..=nums[i] { for v1 in 0..=v2 { if nums[i - 1] - v1 >= nums[i] - v2 && nums[i] - v2 >= 0 { dp[i][v2 as usize] = (dp[i][v2 as usize] + dp[i - 1][v1 as usize]) % modulo; } } } } dp[n - 1].iter().fold(0, |res, &v| (res + v) % modulo) } // 空间压缩 pub fn count_of_pairs(nums: Vec<i32>) -> i32 { let n = nums.len(); let m = *nums.iter().max().unwrap(); let mod_val = 1000000007; let mut dp = vec![vec![0; (m + 1) as usize]; n]; for a in 0..=nums[0] { dp[0][a as usize] = 1; } for i in 1..n { let d = std::cmp::max(0, nums[i] - nums[i - 1]); for j in d..=nums[i] { if j == 0 { dp[i][j as usize] = dp[i - 1][(j - d) as usize]; } else { dp[i][j as usize] = (dp[i][(j - 1) as usize] + dp[i - 1][(j - d) as usize]) % mod_val; } } } dp[n - 1].iter().fold(0, |acc, &x| (acc + x) % mod_val) } }
javascript 解法, 执行用时: 32 ms, 内存消耗: 57.5 MB, 提交时间: 2024-11-28 09:06:21
/** * @param {number[]} nums * @return {number} */ var countOfPairs1 = function(nums) { const n = nums.length; const dp = Array(n).fill(0).map(() => Array(51).fill(0)); const mod = 10 ** 9 + 7; for (let v = 0; v <= nums[0]; v++) { dp[0][v] = 1; } for (let i = 1; i < n; i++) { for (let v2 = 0; v2 <= nums[i]; v2++) { for (let v1 = 0; v1 <= v2; v1++) { if (nums[i - 1] - v1 >= nums[i] - v2 && nums[i] - v2 >= 0) { dp[i][v2] = (dp[i][v2] + dp[i - 1][v1]) % mod; } } } } return dp[n - 1].reduce((sum, v) => (sum + v) % mod, 0); }; // 空间压缩 var countOfPairs = function(nums) { const n = nums.length; const m = Math.max(...nums); const mod = 1e9 + 7; const dp = Array(n).fill(0).map(() => Array(m + 1).fill(0)); for (let a = 0; a <= nums[0]; a++) { dp[0][a] = 1; } for (let i = 1; i < n; i++) { const d = Math.max(0, nums[i] - nums[i - 1]); for (let j = d; j <= nums[i]; j++) { if (j == 0) { dp[i][j] = dp[i - 1][j - d]; } else { dp[i][j] = (dp[i][j - 1] + dp[i - 1][j - d]) % mod; } } } let res = 0; for (let num of dp[n - 1]) { res = (res + num) % mod; } return res; };
golang 解法, 执行用时: 15 ms, 内存消耗: 4.5 MB, 提交时间: 2024-08-12 09:56:17
// 前缀和dp func countOfPairs1(nums []int) (ans int) { const mod = 1_000_000_007 n := len(nums) m := slices.Max(nums) f := make([][]int, n) for i := range f { f[i] = make([]int, m+1) } s := make([]int, m+1) for j := 0; j <= nums[0]; j++ { f[0][j] = 1 } for i := 1; i < n; i++ { s[0] = f[i-1][0] for k := 1; k <= m; k++ { s[k] = s[k-1] + f[i-1][k] // f[i-1] 的前缀和 } for j := 0; j <= nums[i]; j++ { maxK := j + min(nums[i-1]-nums[i], 0) if maxK >= 0 { f[i][j] = s[maxK] % mod } } } for _, v := range f[n-1][:nums[n-1]+1] { ans += v } return ans % mod } // 优化,压缩第一维 func countOfPairs2(nums []int) (ans int) { const mod = 1_000_000_007 n := len(nums) m := nums[n-1] f := make([]int, m+1) for j := range f[:min(nums[0], m)+1] { f[j] = 1 } for i := 1; i < n; i++ { for j := 1; j <= m; j++ { f[j] += f[j-1] // 计算前缀和 } j0 := max(nums[i]-nums[i-1], 0) for j := min(nums[i], m); j >= j0; j-- { f[j] = f[j-j0] % mod } clear(f[:min(j0, m+1)]) } for _, v := range f { ans += v } return ans % mod } // 进一步优化 func countOfPairs(nums []int) (ans int) { const mod = 1_000_000_007 n := len(nums) m := nums[n-1] f := make([]int, m+1) for j := range f[:min(nums[0], m)+1] { f[j] = 1 } for i := 1; i < n; i++ { j0 := max(nums[i]-nums[i-1], 0) m2 := min(nums[i], m) if j0 > m2 { return 0 } for j := 1; j <= m2-j0; j++ { f[j] = (f[j] + f[j-1]) % mod // 计算前缀和 } copy(f[j0:m2+1], f) clear(f[:j0]) } for _, v := range f { ans += v } return ans % mod }
java 解法, 执行用时: 3 ms, 内存消耗: 43.6 MB, 提交时间: 2024-08-12 09:53:05
class Solution { private static final int MOD = 1_000_000_007; private static final int MX = 3001; // MAX_N + MAX_M = 2000 + 1000 = 3000 private static final long[] F = new long[MX]; // f[i] = i! private static final long[] INV_F = new long[MX]; // inv_f[i] = i!^-1 static { F[0] = 1; for (int i = 1; i < MX; i++) { F[i] = F[i - 1] * i % MOD; } INV_F[MX - 1] = pow(F[MX - 1], MOD - 2); for (int i = MX - 1; i > 0; i--) { INV_F[i - 1] = INV_F[i] * i % MOD; } } public int countOfPairs(int[] nums) { int n = nums.length; int m = nums[n - 1]; for (int i = 1; i < n; i++) { m -= Math.max(nums[i] - nums[i - 1], 0); if (m < 0) { return 0; } } return (int) comb(m + n, n); } private long comb(int n, int m) { return F[n] * INV_F[m] % MOD * INV_F[n - m] % MOD; } private static long pow(long x, int n) { long res = 1; for (; n > 0; n /= 2) { if (n % 2 > 0) { res = res * x % MOD; } x = x * x % MOD; } return res; } }
cpp 解法, 执行用时: 21 ms, 内存消耗: 30.8 MB, 提交时间: 2024-08-12 09:52:38
class Solution { public: int countOfPairs1(vector<int>& nums) { const int MOD = 1'000'000'007; int n = nums.size(); int m = ranges::max(nums); vector<vector<long long>> f(n, vector<long long>(m + 1)); vector<long long> s(m + 1); fill(f[0].begin(), f[0].begin() + nums[0] + 1, 1); for (int i = 1; i < n; i++) { partial_sum(f[i - 1].begin(), f[i - 1].end(), s.begin()); // f[i-1] 的前缀和 for (int j = 0; j <= nums[i]; j++) { int max_k = j + min(nums[i - 1] - nums[i], 0); f[i][j] = max_k >= 0 ? s[max_k] % MOD : 0; } } return reduce(f[n - 1].begin(), f[n - 1].begin() + nums[n - 1] + 1, 0LL) % MOD; } int countOfPairs2(vector<int>& nums) { const int MOD = 1'000'000'007; int n = nums.size(), m = nums.back(); vector<int> f(m + 1); fill(f.begin(), f.begin() + min(nums[0], m) + 1, 1); for (int i = 1; i < n; i++) { for (int j = 1; j <= m; j++) { f[j] = (f[j] + f[j - 1]) % MOD; // 计算前缀和 } int j0 = max(nums[i] - nums[i - 1], 0); for (int j = min(nums[i], m); j >= j0; j--) { f[j] = f[j - j0]; } fill(f.begin(), f.begin() + min(j0, m + 1), 0); } return reduce(f.begin(), f.end(), 0LL) % MOD; } int countOfPairs(vector<int>& nums) { const int MOD = 1'000'000'007; int n = nums.size(), m = nums[n - 1]; vector<int> f(m + 1); fill(f.begin(), f.begin() + min(nums[0], m) + 1, 1); for (int i = 1; i < n; i++) { int j0 = max(nums[i] - nums[i - 1], 0); int m2 = min(nums[i], m); if (j0 > m2) { return 0; } for (int j = 1; j <= m2 - j0; j++) { f[j] = (f[j] + f[j - 1]) % MOD; // 计算前缀和 } copy(f.begin(), f.begin() + m2 - j0 + 1, f.begin() + j0); fill(f.begin(), f.begin() + j0, 0); } return reduce(f.begin(), f.end(), 0LL) % MOD; } };
python3 解法, 执行用时: 49 ms, 内存消耗: 16.5 MB, 提交时间: 2024-08-12 09:50:25
# 前缀和优化dp class Solution: def countOfPairs1(self, nums: List[int]) -> int: MOD = 1_000_000_007 n = len(nums) m = max(nums) f = [[0] * (m + 1) for _ in range(n)] for j in range(nums[0] + 1): f[0][j] = 1 for i in range(1, n): s = list(accumulate(f[i - 1])) # f[i-1] 的前缀和 for j in range(nums[i] + 1): max_k = j + min(nums[i - 1] - nums[i], 0) f[i][j] = s[max_k] % MOD if max_k >= 0 else 0 return sum(f[-1][:nums[-1] + 1]) % MOD # 空间优化 def countOfPairs2(self, nums: List[int]) -> int: MOD = 1_000_000_007 m = nums[-1] f = [0] * (m + 1) for j in range(min(nums[0], m) + 1): f[j] = 1 for pre, cur in pairwise(nums): for j in range(1, m + 1): f[j] += f[j - 1] # 计算前缀和 j0 = max(cur - pre, 0) for j in range(min(cur, m), j0 - 1, -1): f[j] = f[j - j0] % MOD for j in range(min(j0, m + 1)): f[j] = 0 return sum(f) % MOD # 进一步优化 def countOfPairs3(self, nums: List[int]) -> int: MOD = 1_000_000_007 m = nums[-1] f = [0] * (m + 1) for j in range(min(nums[0], m) + 1): f[j] = 1 for pre, cur in pairwise(nums): j0 = max(cur - pre, 0) m2 = min(cur, m) if j0 > m2: return 0 for j in range(1, m2 - j0 + 1): f[j] = (f[j] + f[j - 1]) % MOD # 计算前缀和 f[j0: m2 + 1] = f[:m2 - j0 + 1] f[:j0] = [0] * j0 return sum(f) % MOD # 组合数学 def countOfPairs(self, nums: List[int]) -> int: MOD = 1_000_000_007 m = nums[-1] for x, y in pairwise(nums): m -= max(y - x, 0) return comb(m + len(nums), m) % MOD if m >= 0 else 0