4297 截断数组(前缀和 + 后缀和)

1. 问题描述:

给定一个长度为 n 的数组 d1,d2,…,dn。现在,要将该数组从中间截断,得到三个子数组(可以为空)。不妨设第一个子数组包含 a 个元素,第二个子数组包含 b 个元素,第三个子数组包含 c 个元素。那么三个子数组的各元素之和 sum1,sum2,sum3 依次为:

注意,空数组的各元素之和为 0。我们希望截断后的三个子数组满足:sum1 = sum3。满足上一条件的情况下,sum1 尽可能大。请你计算并输出 sum1 的最大可能值。显然,本题一定有解,因为可以令 a = 0,b = n,c = 0。

输入格式

第一行包含整数 n。第二行包含 n 个整数 d1,d2,…,dn。

输出格式

输出一个整数,表示 sum1 的最大可能值。

数据范围

前 6 个测试点满足 1 ≤ n ≤ 10。
所有测试点满足 1 ≤ n ≤ 2 × 10 ^ 5,1 ≤ di ≤ 10 ^ 9。

输入样例1:

5
1 3 1 1 4

输出样例1:

5

输入样例2:

5
1 3 2 1 4

输出样例2:

4

输入样例3:

3
4 1 2

输出样例3:

0
来源:https://www.acwing.com/problem/content/4300/

2. 思路分析:

分析题目可以知道我们只需要让数组最前面的一段与最后面的一段相等即可,由于所有数字都是大于等于1的所以前缀和是不断增大的,所以我们只需要维护前缀和与后缀和即可,使用双指针找到最后一次相等的位置那么数组最前面与最后面的和一定是最大的。

​​​​​​​

3. 代码如下:

class Solution:
    def process(self):
        n = int(input())
        q = list(map(int, input().split()))
        # s1, s2分别为前缀和与后缀和, 下标从1开始比较好处理
        s1, s2 = [0] * (n + 10), [0] * (n + 10)
        for i in range(1, n + 1):
            s1[i] += s1[i - 1] + q[i - 1]
        for i in range(n, 0, -1):
            s2[i] += s2[i + 1] + q[i - 1]
        # 双指针从前往后与从后往前遍历
        i, j = 1, n
        res = 0
        while i < j:
            # 说明i需要往后移动这样两者的和才越靠近
            if s1[i] < s2[j]:
                i += 1
            # j需要往前移动
            elif s1[i] > s2[j]:
                j -= 1
            else:
                # 说明当前找到了相等的区间, 更新答案即可
                res = s1[i]
                i += 1
                j -= 1
        return res


if __name__ == '__main__':
    print(Solution().process())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值