算法 所有奇数长度子数组的和

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

子数组定义为原数组中的一个连续子序列。请你返回 arr 中 所有奇数长度子数组的和 。

示例 1:

输入:arr = [1,4,2,5,3]

输出:58

解释:所有奇数长度子数组和它们的和为:

长度为1的子数组有[1],[4],[2],[5],[3] ,相加结果为15

长度为3的子数组有[1,4,2],[4,2,5],[2,5,3],相加的结果为7+11+10=28

长度为5的子数组有[1,4,2,5,3] ,相加的结果为15

我们将所有值求和得到 15+28+15 = 58

示例 2:

输入:arr = [1,2]

输出:3

解释:只有 2 个长度为1的子数组,[1] 和 [2]。它们的和为 3 。

算法1:按照题目的要求遍历相加即可

int sumOddLengthSubarrays(int* arr, int arrSize)  //效率较低

{  

    int sum = 0;  

    for(int i=1;i<=arrSize;i+=2)//遍历所有奇数的子长度,如1,3,5,...,2n+1  

    {  

        for(int j=0;j<arrSize-i+1;j++)//每一组子数组  

        {  

            for(int k=0;k<i;k++)//把子数组的所有数字相加  

            {  

                sum += arr[j+k];  

            }  

        }  

    }  

    return sum;  

}

算法2:计算每个数字出现的次数,然后相加
根据题意逐步计算子数组的和,发现每个数字都多次出现,多次计算,故思考能否直接计算每个数字的出现次数,思路如下:

1.任取数组下标为i(第i+1个)的元素

2.其左边可以取0~i个元素,共i+1种方案,其中(i+1)/2种为奇数,i/2+1种为偶数

3.右边可以取0~(n-i-1)个元素,共n-i种方案,其中(n-i)/2种为奇数,(n-i+1)/2种为偶数

4.合成子数组须满足条件:左边+本身+右边 = 奇数个,故左奇->右奇,左偶->右偶

5.所以arr[i]的出现次数为lOdd X rOdd + lEven X rEven,即左奇X右奇 + 左偶X右偶

int sumOddLengthSubarrays(int* arr, int arrSize)  

{  

    int res = 0;  

    int lEven,lOdd,rEven,rOdd;//左偶数,左奇数,右偶数,右奇数  

    for(int i=0;i<arrSize;i++)  

    {  

        lOdd = (i+1)/2;  

        lEven = i/2 + 1;  

        rOdd = (arrSize-i)/2;  

        rEven = (arrSize-i+1)/2;  

        res += (lOdd*rOdd + lEven*rEven) * arr[i];  

    }  

    return res;  

}  
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值