Leetcode3250:单调数组对的数目 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. 定义常量 MOD :const int MOD = 1e9 + 7; 定义了一个常量 MOD,用于对结果进行模运算,以避免整数溢出并保持结果在一个可控的范围内。

  2. 类和方法 :定义了一个 Solution 类,其中包含一个 countOfPairs 方法,该方法接收一个整数向量 nums 并返回一个整数,表示满足条件的数对数量。

  3. 初始化累加数组 acc:

    • vector<int> acc(nums[0] + 1, 0); 初始化一个大小为 nums[0] + 1 的数组 acc,所有元素初始化为 0。
    • iota(acc.begin(), acc.end(), 1); 使用 iota 函数将 acc 数组填充为从 1 到 nums[0] 的连续整数。这里的 iota 函数来自 <numeric> 头文件,用于生成一个递增序列。
    • acc 数组用于存储到当前位置为止,所有可能的 nums[i] ^ nums[j](其中 j < i)小于 nums[i] 的数对数量。
  4. 遍历数组 nums:

    • 使用一个迭代器 p 从 nums 的第二个元素开始遍历到最后一个元素。
    • 对于每个 nums[p],创建一个新的临时数组 temp,用于存储计算过程中的中间结果。
  5. 计算部分和:

    • 使用 partial_sum 函数计算 acc 数组中部分元素的和,但只考虑那些可能对当前 nums[p] 产生贡献的元素。
    • partial_sum 的起始范围是 acc.begin() 到 acc.begin() + min(*p, p[-1]) + 1,这确保了只考虑那些异或结果可能小于 nums[p] 的元素。
    • temp.begin() + max(0, *p - p[-1]) 确定了 temp 数组中开始累加的位置,因为只有当 nums[i] ^ nums[j] 的结果落在 [0, nums[p] - 1] 范围内时,数对 (i, p) 才是有效的。
    • 使用自定义的 lambda 函数 [](int sum, int a) { return (sum + a) % MOD; } 来计算累加和,并对结果取 MOD。
  6. 更新 acc 数组:

    • 将 temp 数组赋值给 acc,为下一次迭代做准备。
  7. 返回结果:

    • 最后,acc.back() 存储了整个 nums 数组遍历完成后,所有可能的 nums[i] ^ nums[j] 小于 nums[j] 的数对数量。

代码实现:

cpp 复制代码
const int MOD = 1e9 + 7;
class Solution {
public:
    int countOfPairs(vector<int>& nums) {
        vector<int> acc(nums[0] + 1, 0);
        iota(acc.begin(), acc.end(), 1);

        for (auto&& p = nums.begin() + 1; p != nums.end(); p++) {
            vector<int> temp(*p + 1, 0);
            partial_sum(acc.begin(), acc.begin() + min(*p,p[-1]) + 1, temp.begin() + max(0,*p-p[-1]),
                        [](int sum, int a) { return (sum + a) % MOD; });
            acc = temp;
        }
        return acc.back() ;
    }
};
相关推荐
曦樂~8 小时前
Cpp面筋
c语言·c++
道尔柯南8 小时前
C++ string 类详解:从常用接口到深拷贝,彻底掌握字符串处理
android·java·c++
Dream it possible!11 小时前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
心抵鹊12 小时前
算法之双指针系列(一)
算法·leetcode
十二12 小时前
【洛谷题解】P1083 [NOIP 2012 提高组] 借教室(二分答案 + 差分)
数据结构·c++·算法·蓝桥杯
小此方13 小时前
[算法实战论:动态规划]回文串问题的dp解法,回文串问题的母题,以及以此为基础的派生题
算法·动态规划
Pniubi13 小时前
力扣560.和为k的子数组
算法·leetcode·职场和发展
D e re k ZH14 小时前
C++ 从零入门(一):基础语法与程序结构
数据结构·c++·算法
Pniubi14 小时前
力扣438.找到字符串中所有字母异位词
算法·leetcode·职场和发展
zjxtxdy15 小时前
C++面向对象程序开发-类与对象
开发语言·c++