最大相等分割红包金额 | 豆包MarsCode AI刷题

140 阅读4分钟

问题描述

小U在公司年会上运气极佳,赢得了一等奖。作为一等奖得主,他有机会在一排红包中做两次切割,将红包分成三部分,要求第一部分和第三部分的红包总金额相等。他可以获得的金额是第一部分红包的总金额。帮小U计算出他能从这些红包中拿到的最大奖金金额。

输入是一个整数数组 redpacks,代表红包的金额。输出是小U能获得的最大金额。如果没有满足条件的分割,返回 0

这道题的关键点是:

  1. 找到满足条件的切割点: 第一部分和第三部分的总金额相等。
  2. 计算最大收益: 从所有可能的切割方式中选择最大金额。

挑战点:

  • 如何高效地找到切割点,而不是枚举所有可能的组合。
  • 如何快速判断第一部分和第三部分的总金额是否相等。

代码逻辑

def solution(redpacks):
    # 初始化指针和变量
    p = 0  # 左指针,指向第一部分的末尾
    q = len(redpacks) - 1  # 右指针,指向第三部分的起始
    money = 0  # 保存当前满足条件的最大金额
    left_sum = redpacks[p]  # 第一部分的累计和
    right_sum = redpacks[q]  # 第三部分的累计和

    # 双指针循环,直到两个指针相遇
    while p < q:
        if left_sum < right_sum:
            # 如果第一部分的和小于第三部分的和,移动左指针
            p += 1
            left_sum += redpacks[p]
        elif left_sum > right_sum:
            # 如果第一部分的和大于第三部分的和,移动右指针
            q -= 1
            right_sum += redpacks[q]
            
        if left_sum == right_sum:
            # 如果第一部分和第三部分相等,更新最大金额
            money = left_sum
            # 继续尝试移动两端指针
            p += 1
            q -= 1
            left_sum += redpacks[p]
            right_sum += redpacks[q]
        
    return money

算法设计

代码采用了 双指针 + 累计和 的方式解决问题,流程如下:

1. 双指针初始化

  • p 指向数组的起始位置(左端),表示第一部分的右边界。
  • q 指向数组的末尾(右端),表示第三部分的左边界。
  • left_sum 累计第一部分的金额,初始值为 redpacks[0]
  • right_sum 累计第三部分的金额,初始值为 redpacks[-1]
  • money 用于记录满足条件时的最大金额,初始值为 0。

2. 移动指针,调整金额

  • left_sum < right_sum

    第一部分的金额小于第三部分,说明需要扩大第一部分。移动左指针 p,并将其对应金额加入 left_sum

  • left_sum > right_sum

    第一部分的金额大于第三部分,说明需要扩大第三部分。移动右指针 q,并将其对应金额加入 right_sum

  • 更新后如果left_sum == right_sum

    满足条件时,更新 money = max(money, left_sum)

    为了继续寻找更多可能的切割方案,尝试移动两端指针:p += 1q -= 1,并分别更新 left_sumright_sum

3. 终止条件

  • pq 相遇或交错时,循环结束,返回当前记录的最大金额 money

测试分析

  1. 样例 1

    输入:redpacks = [1, 3, 4, 6, 7, 14] 输出:14

    • 第一次切割后第一部分为 [1, 3, 4, 6] 和为 14,第三部分为 [14] 和为 14。
  2. 样例 2

    输入:redpacks = [10000] 输出:0

    • 无法分成三部分,返回 0。
  3. 样例 3

    输入:redpacks = [10, 10, 10, 10] 输出:20

    • 可切割成 [10, 10] | [10] | [10, 10],金额为 20。
  4. 样例 4

    输入:redpacks = [5, 5, 10, 20, 10, 5, 5] 输出:20

    • 切割后第一部分和第三部分均为 [5, 5, 10],金额为 20。
  5. 样例 5

    输入:redpacks = [7, 7, 7, 21, 7, 7] 输出:14

    • 切割后第一部分和第三部分均为 [7, 7],金额为 14。

复杂度分析

  1. 时间复杂度:

    • 双指针在数组上移动,每个元素最多访问一次,时间复杂度为 O(n)。
  2. 空间复杂度:

    • 仅使用常数额外空间,空间复杂度为 O(1)。