对于一个长度为N的整形数组A,数组里所有的数都是正整数,对于两个满足 0<=X<=Y< N的整数,A[X],A[X+1]…A[y]构成A的一个切片,记作(X,Y)。
用三个下标m1,m2,m3下标满足条件 0< m1,m1+1< m2,m2+1< m3< N-1。
可以把这个整型数组分成(0,m1-1),(m1+1,m2-1),(m2+1,m3-1),(m3+1,N-1)四个切片。如果这四个切片中的整数求和相等,称作等分。
编写一个函数,求一个给定的整型数组是否可以四等分,如果可以,返回一个布尔类型的true,如果不可以返回一个布尔类型的false。
限制条件:数组A最多有1,000,000项,数组中的整数取值范围介于 -1,000,000到1,000,000之间。
要求:函数的计算复杂度为O(N),使用的额外存储空间(除了输入数组外)最多为O(N)。
例子:
对于数组 A=[2,5,1,1,1,1,4,1,7,3,7] 存在下标2,7,9使得数组分成4个分片[2,5],[1,1,1,4],[7],[7],这三个分片内整数之和相等,所以对于这个数组,函数应该返回true
对于数组 A=[10,2,11,13,1,1,1,1,1],找不到能把数组四等分的下标,所以函数应该返回false。
public class Main {
public static void main(String[] args) {
int[] data = new int[]{1,5,6 ,8, 1,5,1,5 ,5, 8,3,1 ,6, 10,1,1 };
System.out.println(get(data));
}
private static boolean get(int[] param){
//下标
int firstIndex = 0, lastIndex = param.length - 1;
//数据
long firstData = 0L,lastData = 0L;
firstData += param[firstIndex];
lastData += param[lastIndex];
while (firstIndex < lastIndex - 1){
if(firstData < lastData){
firstIndex ++;
firstData += param[firstIndex];
}else if (firstData > lastData){
lastIndex -- ;
lastData += param[lastIndex];
}else {
int secondIndex = firstIndex + 2;
int thirdIndex = lastIndex - 2;
long secondData = 0L;
long thirdData = 0L;
while (secondIndex < thirdIndex-1 ){
if(firstData > secondData){
secondData += param[secondIndex];
//判断数据是否已经相等
if (firstData != secondData){
secondIndex ++ ;
}
}
if (lastData > thirdData){
thirdData += param[thirdIndex];
//判断数据是否已经相等
if (lastData != thirdData){
thirdIndex -- ;
}
}
if( firstData < secondData || lastData < thirdData){
//出现数据已经不正确直接
break;
}
if (firstData == secondData && secondData == thirdData){
// 下标相差2
if(secondIndex + 1 == thirdIndex - 1){
// 成功
System.out.println("第一个下标:" + (firstIndex + 1));
System.out.println("第二个下标:" + (secondIndex + 1));
System.out.println("第三个下标:" + (lastIndex - 1));
return true;
}else {
// 数值均相等,但不能分成4个数组,重新计算
break;
}
}
}
// 1 == 4 ,但无法分割数组,继续尝试
firstIndex ++;
lastIndex --;
firstData += param[firstIndex];
lastData += param[lastIndex];
}
}
return false;
}
}