浅谈 所有奇数长度子数组的和 问题

所有奇数长度子数组的和

问题:
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和

思路
例:
输入:arr = [1, 4, 2, 5, 3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1, 4, 2] = 7
[4, 2, 5] = 11
[2, 5, 3] = 10
[1, 4, 2, 5, 3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58

  1. 求出数组中各位数在奇数子数组中出现的次数。
  2. 将数组里的每个数乘以出现的次数再求和则得到所有可能的奇数长度子数组的和。
    如上例 1 出现 3 次,4 出现 4 次,2 出现 5 次,5 出现 4 次,3 出现 3 次
    求和: 1 * 3 + 4 * 3 + 2 * 4 + 5 * 4 + 3 * 3 = 58
    需要弄清楚 arr[i] 左边有 i + 1 个数,右边有 len - i 个数,len 为数组规模。
    左边找偶数个数,右边也应为偶数个数。
    左边找奇数个数,右边也只能是奇数个数。
    只有这样加上自身组合起来才是 奇数长度的子数组
    arr[i] 前面共有 i + 1 个选择,后面共有 len - i 个选择(0 个也是一种选择)。
    由于组合的子数组必须为连续的数组元素组成
    所以 找偶数个数字的子串为总的选择加一的一半,找奇数个数字的子串为总的选择的一半。
    如 有十个数,偶数个数字的子串长度分别为 0 2 4 6 8 10 → 6 个(选择有 11 种)
    奇数个数字的子串长度分别为 1 3 5 7 9 → 5 个
class Solution {
public:
    int sumOddLengthSubarrays(const vector<int>& arr) const {
        auto sum = 0;
        auto len = arr.size();
        for(auto i = 0; i < len; ++i) {
            int left_choices = i + 1, right_choices = len - i,
            left_odd = left_choices / 2, right_odd = right_choices / 2,
            left_even = (left_choices + 1) / 2, right_even = (right_choices + 1) / 2;
            sum += arr[i] * (left_odd * right_odd + left_even * right_even); 
        }
        return sum;
    }
};
上一篇:Django中的Model字段


下一篇:批量处理