首先让我们看一下题目需求
小U在公司年会上运气极佳,赢得了一等奖。作为一等奖得主,他有机会在一排红包中做两次切割,将红包分成三部分,要求第一部分和第三部分的红包总金额相等。他可以获得的金额是第一部分红包的总金额。帮小U计算出他能从这些红包中拿到的最大奖金金额。
样例1:
输入:
redpacks = [1, 3, 4, 6, 7, 14]输出:14
需求分析
从题目可知,我们需要求出一个能得奖的最大奖金金额,而想要获得这个奖金就需要从一排红包(数组)中做两次切割,要求第一部分和第三部分的红包金额相等。
这里我们可以简单的画一个图
其实就是需要我们在A和C相等的情况下使A最大化,那么就涉及到对AC是否相等的判断,同时还需要求最大值,在这里,我们可以使用双指针的方法
以样例给出的redpacks = [1, 3, 4, 6, 7, 14]为例
首先我们构建一个leftIndex,指向数组0索引处,构建一个rightIndex,指向数组reapacks.length(),即最后一个索引处
同时,我们还需要创建两个整型来储存左右两个部分分别储存的值,在这里设为leftCount与rightCount,接着,我们就可以开始遍历了。
第一次移动
leftcount=1,rightcount=14
右部分大于左部分,我们移动左边指针,使leftIndex指向1索引,leftcount=leftcount+redpacks[1](下方红色数字为数组所对应索引)
第二次移动
继续对leftcount与rightcount进行判断
leftcount=4<rightcount=14
右部分大于左部分,依然移动左边指针,使leftIndex指向2索引,leftcount=leftcount+redpacks[2]
我们就按照这个步骤依次移动指针,直到leftcount==rightcount时
第n次移动,直到leftcount==rightcount时
当我们将leftIndex移动至索引3时,我们能够发现leftcount==rightcount,而很明显在这一题中这个leftcount的值正是我们所需要的答案14,那么在以后我们遇到左右部分相等时,我们可以直接将该值作为结果进行返回吗,很明显是不行的,因为在题目所给数组长度更长的条件下,第一次相等的值往往不是我们所求的答案,所以这时候我们可以创建一个resultcount用于储存当前搜寻到的最大值
当接着接着遍历时
这样就能完美的解决这个问题啦~
以下为在Java中的实现代码
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(List<Integer> redpacks) {
if (redpacks.size()==1)return 0;
int rightIndex=redpacks.size()-1;
int leftIndex=0;
int rightcount=0;
int leftcount=0;
int resultcount=0;
while(leftIndex<rightIndex){
Integer right = redpacks.get(rightIndex);
rightcount=right+rightcount;
while(leftcount<rightcount){
Integer left = redpacks.get(leftIndex);
leftcount=leftcount+left;
leftIndex++;
}
if (rightcount==leftcount)resultcount=rightcount;
rightIndex--;
}
return resultcount;
}
总结
在处理数组或链表这类线性数据结构问题中我们都可以考虑能否使用双指针来解决问题:
一方面,双指针可以减少遍历次数,提高算法的效率,也可将复杂问题简化为更简单的子问题。同时双指针无需在内存中扩展原先空间,可以很好的减少空间复杂度。但另一方面,在使用双指针解决问题时,我们需要注意索引超出的情况,同时要避免陷入无限循环的困境,这就需要我们提前对需求进行分析后再进行具体的代码实现。
需要注意的是,双指针一般只适用于线性数据结构问题,像树、图等非线性结构很难进行使用,可能需要其他的方法进行解决。