题目:
我们是这样定义数组 中心索引 的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
如果想看正确答案直接看思路(2),思路(1)没写出来。
思路:(1)
双指针索引方法,一个从左边开始加,一个从右边开始加,如果左边和大于右边和就右边指针索引向左移动一下,否则左边移动一下,直到两个指针相遇了,判断两边和相等不,如果相等就返回这个位置,如果不等就返回-1。
以上是我一开始的想法,后来我意识到了负数的存在,比如下面的第二个用例,如果左边小于右边,则左边的指针向右移动的话,那么一移到底,导致输出5(答案1);然后我就开始考虑,四种情况(左右下一位分别的正负)正正,正负,负正,负负,我一开始的解决思路判断两者的绝对值,选择让左边和与右边和的差距最少的情况;但我又想到了一个用例{4,5,7,-15,8,4}其正确答案是1,这个用例的索引2到4相加等于零,而索引1又是中心索引,所以它们四个的值并不重要,比如{4,-5,-7,15,-8,4},{4,5,7,1,-8,4},{4,-5,7,-15,8,4};所以以上说的四种情况在这个例子里指针移动的情况应该是相同的,然后我就心态炸了。我还想过解决方案就是每当左右两边相等时就判断左右指针之间的值在去掉中心索引后,相加和是否为零,是就输出答案,但这个思路就太复杂了,哪怕写出来也会想我下面思路(1)的代码一样到处是if else,不够简洁,所以果断溜了;
搞不定的用例:
int[] num={-1,-1,1,1,1,0};//2
int[] nums={-1,-1,-1,-1,1,0};//1
这是我这个思路的最后一次代码,我自己都看不下去了,没写出来。
public int pivotIndex(int[] nums) {
//去掉空集
if(nums.length==0||nums.length==1||nums.length==2){
return -1;
}
//左右指针
int i=1,j=nums.length-2;
//左右元素和
int left=nums[0],right=nums[nums.length-1];
while(i<j){
//判断左右和的大小
if(left<right){
//如果是正数直接加。如果是负数,则判断绝对值
if(nums[i]>=0||(nums[i]+nums[j]>=0)){
left+=nums[i];
i++;
}else{
right+=nums[j];
j--;
}
}else if(left>right){
//如果是正数直接加。如果是负数,则判断绝对值
if(nums[j]>=0||(nums[i]+nums[j]>=0)){
right+=nums[j];
j--;
}else{
left+=nums[i];
i++;
}
}else if(left==right){
int sum=0;
//每当左右两边相等时就判断左右指针之间的值在去掉中心索引后,相加和是否为零,是就输出答案
for(int k=i;k<=j;k++){
sum+=nums[k];
}
if(sum==nums[i]){
return i;
}else{
if(nums[i]>=0||(nums[i]+nums[j]>=0)){
left+=nums[i];
i++;
}else{
right+=nums[j];
j--;
}
}
}
}
//左右和相等且移动过
if(left==right&&(i!=0||j!=0)){
System.out.println(left+right);
return i;
}
return -1;
}
思路:(2)
算出所有数的总和之后,直接从左边开始加什么时候等于总和的一半为止,如果没找到就返回-1;
代码:
public int pivotIndex(int[] nums) {
if(nums.length<3){
return -1;
}
//求总和
int sum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
}
//左边的和
int temp=0;
for(int i=0;i<nums.length;i++){
if((temp==(sum-nums[i])/2)&&((sum-nums[i])%2==0)){
return i;
}else{
temp+=nums[i];
}
}
return -1;
}
这个就简洁了很多