Leetcode——Array-1588. 所有奇数长度子数组的和

Leetcode——Array-1588. 所有奇数长度子数组的和

1.题目描述

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

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

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

示例 1:

输入: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
示例 2:

输入:arr = [1,2]
输出:3
解释:总共只有 2 个长度为奇数的子数组,[1] 和 [2]。它们的和为 3 。
示例 3:

输入:arr = [10,11,12]
输出:66

提示:

1 <= arr.length <= 100
1 <= arr[i] <= 1000

2.解题思路

其实想法很简单,相对也比较套路。就是遍历一遍所有的元素,然后查看这个元素会在多少个长度为奇数的数组中出现过。

比如题目给出的第一个测试用例 [1, 4, 2, 5, 3] 中;

1 在 3 个长度为奇数的数组中出现过:[1], [1, 4, 2], [1, 4, 2, 5, 3];所以最终的和,要加上 1 * 3;

4 在 4 个长度为奇数的数组中出现过:[4], [4, 2, 5], [1, 4, 2], [1, 4, 2, 5, 3];所以最终和,要加上 4 * 4;

2 在 5 个长度为奇数的数组中出现过:[2], [2, 5, 3], [4, 2, 5], [1, 4, 2], [1, 4, 2, 5, 3];所以最终和,要加上 5 * 2;

下面的关键就是,如何计算一个数字在多少个奇数长度的数组中出现过?

对于一个数字,它所在的数组,可以在它前面再选择 0, 1, 2, … 个数字,一共有 left = i + 1 个选择;

可以在它后面再选择 0, 1, 2, … 个数字,一共有 right = n - i 个选择。

如果在前面选择了偶数个数字,那么在后面,也必须选择偶数个数字,这样加上它自身,才构成奇数长度的数组;

如果在前面选择了奇数个数字,那么在后面,也必须选择奇数个数字,这样加上它自身,才构成奇数长度的数组;

数字前面共有 left 个选择,其中偶数个数字的选择方案有 left_even = (left + 1) / 2 个,奇数个数字的选择方案有 left_odd = left / 2 个;

数字后面共有 right 个选择,其中偶数个数字的选择方案有 right_even = (right + 1) / 2 个,奇数个数字的选择方案有 right_odd = right / 2 个;

所以,每个数字一共在 left_even * right_even + left_odd * right_odd 个奇数长度的数组中出现过。

作者:liuyubobobo
链接:https://leetcode-cn.com/problems/sum-of-all-odd-length-subarrays/solution/cong-on3-dao-on-de-jie-fa-by-liuyubobobo/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3.程序代码

class Solution:
    def sumOddLengthSubarrays(self, arr: List[int]) -> int:
        res = 0
        for i in range(len(arr)):
            left = i+1
            right = len(arr)-i
            lefteven = (left+1)//2
            leftodd = (left)//2
            righteven = (right+1)//2
            rightodd = (right)//2
            res += (lefteven*righteven + rightodd*leftodd)*arr[i]
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值