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

80 阅读2分钟

问题描述

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

测试样例

  • 样例1

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

  • 样例2

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

  • 样例3

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

  • 样例4

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

  • 样例5

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

解题思路

  • 涉及前后和的相等:使用双指针
  • 移动指针:当第一部分的和大于第三部分的和时,后面指针向前移动。当第三部分大于第一部分时,前面的指针向后移动。当一三部分的和相等时,保存结果,并且同时移动前后两个指针。

代码实现

第一步

判断输入是否符合要求当输入长度小于2时,直接返回结果

	if len(redpacks)<2{
		return 0
	}

第二步

设置前后两个指针i,j。并初始化,i为-1,j为切片长度。这样初始化的目的为方便后续代码逻辑判断。

  i,j := -1,len(redpacks)
	left,right := 0,0
	res := 0

第三步

设置变量left,为第一部分的和,right为第二部分的和,res为需要返回的结果。当i<j时,不断移动指针的位置。可能出现的情况1:left与right相等。此时i往右边移动,j往左边移动。并且left需要加上右移后的数字,right需要加上左移后的数字。情况2:left>right。说明前面部分的和太大了,此时需要左移j,随后right加上左移后的数字。情况3:left<right,说明前面部分的和太小了,此时需要右移i,随后left加上右移后的数字。不断循环,直到不满足条件,最后res的值就为结果。

  left,right := 0,0
	res := 0
	for i<j {
		if left==right{
			res = left
			i++
			j--
			left += redpacks[i]
			right += redpacks[j]
		}else if left<right{
			i++
			left += redpacks[i]
		}else {
			j--
			right += redpacks[j]
		}
	}

总结

首先明确使用什么算法,该题所需前后部分的和所以明显需要使用到双指针。确定何时需要停止循环,前后部分和的构成一定不包含同一个数,所以i<j即可。判断各种条件时指针所需要的移动。 算法时间复杂度为O(n)。