返回

菜狗题解:前缀和(C++)——力扣第278场周赛第二题

后端

在力扣第278场周赛中,第二题是一道有关前缀和的题目。题目的如下:

给你一个长度为 n 的数组 nums,它包含 0 和 1。请你找到所有满足以下条件的下标对 (i, j):

  • i < j
  • nums[i] = 1
  • nums[j] = 1
  • 在区间 [i+1, j-1] 中,nums[k] = 0

简而言之,我们要求出满足上述条件的子数组的个数。

解决这道题的方法之一是使用前缀和来计算区间中 0 和 1 的个数。前缀和是一种数据结构,它存储了数组中每个元素到当前元素的和。通过使用前缀和,我们可以快速地计算出一个区间中元素的和。

以下是解决这道题的步骤:

  1. 创建一个长度为 n+1 的数组 prefix,其中 prefix[i] 表示 nums[0] 到 nums[i-1] 的和。
  2. 遍历数组 nums,并计算出每个位置的左右前缀和。左前缀和是 prefix[i] - prefix[i-1],右前缀和是 prefix[n] - prefix[i+1]。
  3. 对于每个位置 i,如果 nums[i] = 1,那么我们就可以使用左右前缀和来计算出以 i 为中心满足条件的子数组的个数。具体来说,我们可以计算出以 i 为中心且左右前缀和分别为 x 和 y 的子数组的个数。这个数量是 x * y。
  4. 将所有满足条件的子数组的个数累加起来,即可得到最终答案。

使用上述方法,我们可以快速地解决这道题。

代码实现:

class Solution {
public:
    long long countExcellentPairs(vector<int>& nums, int k) {
        int n = nums.size();
        vector<long long> prefix(n + 1, 0);
        for (int i = 0; i < n; i++) {
            prefix[i + 1] = prefix[i] + nums[i];
        }

        long long ans = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] == 1) {
                int left = prefix[i] - prefix[i - 1];
                int right = prefix[n] - prefix[i + 1];
                ans += left * right;
            }
        }

        return ans;
    }
};

时间复杂度:O(n)。

空间复杂度:O(n)。