题目描述
给定一个整数类型的数组 nums
,请编写一个能够返回数组“中心索引”的方法。
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
注意:
- nums 的长度范围为 [0, 10000]。
- 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。
要点分析
- 左侧和右侧元素相加时,均不包括中心索引的元素;
- 要擅于利用数学关系:
左侧和 + 中心索引元素 + 右侧和 = 总和
左侧和 = 右侧和
即可得判断条件:左侧和 = 总和 - 中心索引元素 - 左侧和
进一步转换:左侧和 * 2 = 总和 - 中心索引元素 - 题目提示的元素范围包括负数,使用双指针法时需要注意。
方法一:数学关系
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
Sum = sum(nums)
leftsum = 0
for i, x in enumerate(nums):
if leftsum == (Sum - leftsum - x):
return i
else:
leftsum += x
return -1
- 擅于利用Python的特性,灵活调用内嵌函数。
方法二:双指针法
这个要注意的点比较多
-
考虑左右边界:
中心索引为头尾的情况:有元素一侧之和为0 -
双指针方向
起初设定双指针在两头,通过对比两侧元素之和来判断移动哪一指针,出现过一下问题:- 由于元素可能为负数,因此和较小的一侧即使多加一个元素也不一定能够逼近另一侧;
- 当两侧元素和相等时,两指针之间可能存在不止一个元素,不符合题意。
进一步观察中心索引的特点可知,只要两指针之间保持一的索引的距离,分别向两侧求和并进行比对即可,因此双指针均设定为从左侧开始。
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
# 排除空列表情况
if not nums:
return -1
Sum = sum(nums)
# 处理左边界
if nums[0] == Sum:
return 0
# 双指针操作(以两侧之和表示)
leftsum = nums[0]
rightsum = Sum - leftsum - nums[1]
for i in range(1,len(nums)-1):
if leftsum == rightsum:
return i
# 否则双双右移
leftsum += nums[i]
rightsum -= nums[i+1]
# 处理右边界
if nums[-1] == Sum:
return len(nums)-1
return -1
- 之所以要最后处理右边界是因为会出现一下这种情况:
[-1,-1,1,1,0,0]
如果在前面处理右边界则会直接返回索引5,但事实上索引4也是中心索引,题目要求有多个时返回最左侧的那个,因此需要通过双指针移动来判断是否有更靠左侧的索引。 - 总体来说,左边界 -> 双指针自左向右移动判断 -> 右边界。