文巾解题1588. 所有奇数长度子数组的和

1 题目描述

 2 解题思路

2.1 直接求解

枚举子数组的长度和首位置

class Solution:
    def sumOddLengthSubarrays(self, arr: List[int]) -> int:
        l=len(arr)
        ret=0
        for i in range(1,l+1,2):
            for j in range(l-i+1):
                ret+=sum(arr[j:j+i])
        return(ret)

2.2 直接求解+前缀和

class Solution:
    def sumOddLengthSubarrays(self, arr: List[int]) -> int:
        l=len(arr)
        s=[0]
        for i in arr:
            s.append(s[-1]+i)
        ret=0
        for i in range(1,l+1,2):
            #子序列长度1~l,每次增长2
            for j in range(l-i+1):
                #子序列起始点,最大为l-i(此时的终点为l-i+i-1=l-1)
                ret+=s[i+j]-s[j]
        return(ret)

2.3 双指针

        首先把问题转化成,每个数存在在多少个奇数子数组中,也就是每个数重复了多少次。

        很容易发现数组的第一个数,重复的次数由总长决定。奇数的子数组有多少个呢,正好是(length + 1) // 2。

        那么前一个数和后一个数是否存在依赖关系呢?
        观察到,第一个数组成长度3、5、7等长度的子数组的时候,始终带着第二个数,但长度为1的时候没有第二个数出现。

        

        同样的,从第二个数往后面组成的子数组和第一个数没有关系。
也就是说,第二个数出现了第一个数出现的次数,但是少了第一个数出现、第二个数没出现的次数。而且第二个数还比第一个数多了第二个数出现、第一个数没出现的次数。上一个数出现的次数可以记录。
       

         那么上一个数出现,当前的数没出现有多少次呢?正好是一个递归思想,数组从0到i-1构成多少个包含i-1的子数组,就又是长度计算的。(根据对称性,这又等于从0到i-1构成多少个包含0的子数组)

        而当前的数出现,上一个数没出现,又正好是i到n-1构成多少个包含i的子数组,同样是长度计算的。

        于是我们知道以下信息:

  •         在数组1~n中,第一位出现(n+1)//2次
  •         当前位比上一位多 (n - i + 1) // 2 - (i + 1) // 2
  •         首尾对应位置出现次数相同(对称性)
class Solution:
    def sumOddLengthSubarrays(self, arr: List[int]) -> int:
        l=len(arr)

        begin, end  , ret, times = 0, n - 1, 0, (n+1) // 2
        while begin <= end:
            # 对称性,前后对称位置出现的次数一样
            if begin< end:
                ret += times * (arr[l] + arr[r])
            else:
                ret += times * arr[l]
            begin += 1
            end -= 1
            
            times += (l- begin + 1) // 2 
            '''
            下一个数比前一个数多的部分:
            后一个数构成的不带前一个数的奇数子数组的个数
            也即以下一个数为第一个数,剩余数组中奇数子数组个数
            '''
            
            times -= (begin + 1) // 2
            '''
            下一个数比前一个数少的部分:
            前一个数构成的不带后一个数的奇数子数组的个数
            也即第一个数为首个数,到l之前为止,这一个子数组中奇数子数组的个数
            '''
        return ret

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UQI-LIUWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值