[LeetCode] 5503. 所有奇数长度子数组的和 普通解法和大神解法

给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。

子数组 定义为原数组中的一个连续子序列。

请你返回 arr 中 所有奇数长度子数组的和 。


我们只需要枚举所有的奇数长度的子数组即可。

class Solution {
public:
    int sumOddLengthSubarrays(vector<int>& arr) {
        int res = 0;
        for(int i = 0; i < arr.size(); ++i){
            for(int step = 1; i + step <= arr.size(); step += 2){
                res += accumulate(arr.begin() + i, arr.begin() + i + step, 0);
            }
        }
        return res;
    }
};

在上面的解法中,accumulate的本质就是在计算从 arr[i] 到 arr[i + step - 1] 的连续子数组的和。计算连续子数组的和,很容想到可以使用前缀和(Prefix Sum)的方式。使用 O(n) 的时间可以预处理前缀和数组,之后使用 O(1) 的时间即可计算出一个连续子数组的和。

时间复杂度是 O(n^2) 的,空间复杂度是 O(n) 的。

class Solution {
public:
    int sumOddLengthSubarrays(vector<int>& arr) {
        vector<int> persum = {0};
        for(int e: arr)
            persum.push_back((persum.back() + e));
        int res = 0;
        for(int i = 0; i < arr.size(); ++i){
            for(int step = 1; step + i <= arr.size(); step += 2){
                res += persum[i + step] - persum[i];
            }
        }
        return res;
    }
};

这个问题有 O(n) 的解法。

  • odd奇数,even偶数
  • 对于每个元素i(数组中下标为i)来说,要构成奇数长度的子数组
    即 i左边的元素个数left+i本身自己一个+右边元素的个数right=奇数
    即 left+right=偶数
  • 满足a+b=偶数就只有两种情况
    1. 奇数+奇数=偶数
    2. 偶数+偶数=偶数
  • 所以只需要求得i左边可以选择奇数长度的可能有多少种,即left_odd,同样求右边奇数right_odd
    就可以求出策略1有多少种可能
    所以只需要求得i左边可以选择偶数长度的可能有多少种,即left_odd,同样求右边偶数right_odd
    就可以求出策略1有多少种可能,注意0也算选择的一种可能
  • 即元素i在所有奇数长度子数组出现的次数总和是
    left_oddright_odd+left_evenright_even
  • 元素i左边元素共有i个,右边元素共有siz-i-1个

class Solution {
public:
int sumOddLengthSubarrays(vector& arr) {

    int res = 0;
    for(int i = 0; i < arr.size(); i ++){
        int left = i + 1, right = arr.size() - i,
            left_even = (left + 1) / 2, right_even = (right + 1) / 2,
            left_odd = left / 2, right_odd = right / 2;
        res += (left_even * right_even + left_odd * right_odd) * arr[i];
    }
    return res;
}

};

O(n) 的解法可以应对 10^6 乃至 10^7 的数字规模。如果这道题的数字规模是这样的,那么上面两种解法都将超时,这个问题也就变成了一个 Medium 甚至是 Hard 的问题了吧:)

欢迎关注公众号,往期内容也很精彩。每周更新面试高频算法题。从思路,代码,时间复杂度等多方面进行分析。
后台点击电子书可以获得:halfrost大神的孔雀书,经典巨著:算法导论。

[LeetCode] 5503. 所有奇数长度子数组的和 普通解法和大神解法_第1张图片

你可能感兴趣的:(LeetCode,刷题,c++,算法)