五月集训(第08天)—— 前缀和

前缀和

1. 1480. 一维数组的动态和

    思路:
        求数组前缀和

class Solution {
public:
    vector<int> runningSum(vector<int>& nums) {
        int n = nums.size();
        for (int i = 1; i < n; i++)
            nums[i] = nums[i] + nums[i - 1];
        return nums;
    }
};

2. 1588. 所有奇数长度子数组的和

    思路:
        先得到数组前缀和。利用两个指针维护每次子数组的长度,j-i-1 ~ ji为需要求和的区间长度。利用前缀和差分得到区间内的数字和。

class Solution {
public:
    int sumOddLengthSubarrays(vector<int>& arr) {
        int n = arr.size();
        int pre = 0, ans = 0;
        for (int i = 1; i < n; i++) arr[i] += arr[i - 1];
        for (int i = 0; i < n; i += 2) {
            for (int j = i; j < n; j++) {
                if (j - i == 0) pre = 0;
                else pre = arr[j - i - 1];
                ans += arr[j] - pre;
            }
        }
        return ans;
    }
};

3. 1442. 形成两个异或相等数组的三元组数目

    思路1: 三重循环
        利用异或和的性质,同为0,异为1。求出数组的前缀异或和。a = arr[j - 1] ^ arr[i - 1]; b = arr[k] ^ arr[j - 1];, a == b即为a ^ b == 0, 即为arr[k] == arr[i - 1],注意特判i == 0的情况,防止数组越界访问。

class Solution {
public:
    int countTriplets(vector<int>& arr) {
        int n = arr.size();
        int ans = 0;
        int a, b;
        for (int i = 1; i < n; i++) arr[i] ^= arr[i - 1];
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                for (int k = j; k < n; k++) {
                    // if (i == 0) a = arr[0];
                    // else a = arr[j - 1] ^ arr[i - 1];
                    // b = arr[k] ^ arr[j - 1];
                    if (i == 0) {
                        if (arr[k] == 0)
                            ans++;
                    }
                    else if (arr[k] == arr[i - 1])
                        ans++;
                }
            }
        }
        return ans;
    }
};

    思路2: 二重循环
        在 [i + 1, k]之间的j都满足,所以一次ans += k - i;,可以把j的循环省去。

class Solution {
public:
    int countTriplets(vector<int>& arr) {
        int n = arr.size();
        int ans = 0;
        int a, b;
        for (int i = 1; i < n; i++) arr[i] ^= arr[i - 1];
        for (int i = 0; i < n - 1; i++) {
            for (int k = i + 1; k < n; k++) {
                // 在 [i + 1, k]之间的j都满足,所以一次ans += k - i;
                if (i == 0) {
                    if (arr[k] == 0)
                        ans += k - i;
                }
                else if (arr[k] == arr[i - 1])
                    ans += k - i;
            }
        }
        return ans;
    }
};

    思路3: 哈希表 + 一重循环
        思路地址

4. 1094. 拼车

    思路:
        参考leetcode大佬优秀思路。
在这里插入图片描述


class Solution {
public:
    bool carPooling(vector<vector<int>>& trips, int capacity) {
        vector<int> d(1005);
        for (auto &e : trips) {
            d[e[1]] += e[0];
            d[e[2]] -= e[0];
        }
        for (int i = 0; i < 1000; i++) {
            if (i) d[i] += d[i - 1];
            if (d[i] > capacity) return false;
        }
        return true;
    }
};
posted @ 2022-05-08 18:59  番茄元  阅读(13)  评论(0)    收藏  举报