2026-07-01:找出最小平衡下标。用go语言,给你一个整数数组 nums。我们要找“平衡下标”里最小的那个下标 i。
对任意下标 i,把数组分成左右两部分:
• i 左边的所有元素求和,记为 leftSum(如果左边没有元素,那么 leftSum = 0)。
• i 右边的所有元素求乘积,记为 rightProd(如果右边没有元素,那么 rightProd = 1)。
如果满足 leftSum == rightProd,则这个 i 就称为“平衡下标”。
最后返回所有满足条件的下标中最小的那个;如果一个都找不到,返回 -1。
1 <= nums.length <= 100000。
1 <= nums[i] <= 1000000000。
输入: nums = [2,1,2]。
输出: 1。
解释:
对于下标 i = 1:
左侧总和 = nums[0] = 2
右侧乘积 = nums[2] = 2
由于左侧总和等于右侧乘积,下标 1 是平衡下标。
没有更小的下标满足条件,因此答案是 1。
题目来自力扣3862。
一、分步详细执行流程
数组长度=3,初始状态:sum=0,mul=1,l=0,r=2
循环条件:l < r,只要左右指针没相遇就持续迭代。
第1轮循环:l=0,r=2,l
比较sum(0)和mul(1):0 < 1,走左侧累加分支
1. 将
nums[l]=nums[0]=2加到 sum:sum = 0 + 2 = 22. 左指针右移:l = 0 + 1 = 1
本轮结束状态:sum=2,mul=1,l=1,r=2
比较sum(2)和mul(1):2 > 1,走右侧累乘分支
1. 溢出预判:检查
mul * nums[r]是否超 1e14。当前 mul=1,nums[r]=nums[2]=2,1*2=2 < 1e14,无溢出风险2. 右侧乘积更新:mul = 1 * 2 = 2
3. 右指针左移:r = 2 - 1 = 1
本轮结束状态:sum=2,mul=2,l=1,r=1
此时 l=1、r=1,l < r条件不成立,跳出循环。
循环后校验平衡条件
判断sum == mul:2 == 2,条件成立,返回当前 l 值 1,和题目输出一致。
二、通用场景完整逻辑拆解(不局限示例) 步骤1:初始化变量
1. 求和变量 sum 初始为0:代表分割点左侧无元素时的初始和;
2. 乘积变量 mul 初始为1:代表分割点右侧无元素时的初始乘积;
3. 左指针 l 从数组最左端0开始;
4. 右指针 r 从数组最后一个下标
len(nums)-1开始。
每次循环分两种分支判断:
分支A:sum < mul,扩充左侧区间
说明当前分割点偏右,需要把左边下一个元素纳入左侧求和区间:
1. 左指针指向的元素 nums[l] 累加进 sum;
2. 左指针 l 向右移动一位,代表候选平衡下标右移一位。
说明当前分割点偏左,需要把右边下一个元素纳入右侧求积区间:
1. 溢出校验:判断
mul > 1e14 / nums[r]。若成立,代表mul * nums[r]会超出设定上限,乘积会无限变大不可能和有限的sum相等,直接返回-1结束程序;2. 无溢出则将 nums[r] 乘入 mul;
3. 右指针 r 向左移动一位。
l 和 r 指针重合时停止循环,此时重合位置 l 就是唯一候选平衡下标。
原理:双指针不断收拢区间,最终重合点恰好对应:左边全部是 [0, l-1](累加和sum)、右边全部是 [l+1, end](累乘积mul),完美匹配平衡下标i=l的左右计算规则。
步骤3:循环结束后校验平衡条件
1. 若 sum(i=l左侧总和)等于 mul(i=l右侧乘积),说明 l 是合法平衡下标,直接返回 l;
2. 若两者不相等,不存在任何平衡下标,返回 -1。
当右侧累乘即将溢出 1e14 时直接返回-1:
数组元素最小为1,一旦乘积突破1e14,后续只会越乘越大,而左侧求和是线性增长、增速远慢于乘积,二者永远无法相等,提前剪枝避免无效循环与数值溢出崩溃。
三、时间复杂度分析
整个算法只有一层 while 循环,左指针 l 只向右移动、右指针 r 只向左移动,两个指针合计最多遍历数组全部元素一次,每个元素只会被 l 或 r 访问恰好1次。
数组长度记为 n(1 ≤ n ≤ 1e5):
• 总操作次数 ≤ n
• 时间复杂度:O(n)
算法仅定义固定数量临时变量:sum、mul、l、r,没有开辟任何随数组长度n变化的数组、切片、哈希表等存储空间,额外空间与输入规模无关。
• 额外空间复杂度:O(1)(常数级空间)
package main
import (
"fmt"
)
func smallestBalancedIndex(nums []int)int {
sum, mul := 0, 1
l, r := 0, len(nums)-1
for l < r {
if sum < mul {
sum += nums[l]
l++
} else {
if mul > 1e14/nums[r] {
return-1
}
mul *= nums[r]
r--
}
}
if sum == mul {
return l
}
return-1
}func main() {
nums := []int{2, 1, 2}
result := smallestBalancedIndex(nums)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
from typing import List
def smallest_balanced_index(nums: List[int]) -> int:
sum_val = 0
mul_val = 1
l, r = 0, len(nums) - 1
while l < r:
if sum_val < mul_val:
sum_val += nums[l]
l += 1
else:
# 检查乘法是否会溢出
if mul_val > 10**14// nums[r]:
return-1
mul_val *= nums[r]
r -= 1
if sum_val == mul_val:
return l
return-1if __name__ == "__main__":
nums = [2, 1, 2]
result = smallest_balanced_index(nums)
print(result)
C++完整代码如下:
using namespace std;
int smallestBalancedIndex(vector& nums) {
long long sum = 0;
long long mul = 1;
int l = 0, r = nums.size() - 1;
while (l < r) {
if (sum < mul) {
sum += nums[l];
l++;
} else {
// 检查乘法是否会溢出
if (mul > 100000000000000LL / nums[r]) {
return-1;
}
mul *= nums[r];
r--;
}
}
if (sum == mul) {
return l;
}
return-1;
}int main() {
vector nums = {2, 1, 2};
int result = smallestBalancedIndex(nums);
cout << result << endl;
return0;
}
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。
热门跟贴