🎮 空间复杂度O(1)?村长说这是节俭美德!
“小白,村里要搞个村运会!”村长塞给我一张皱巴巴的纸,上面歪歪扭扭画着一排数字:[10, 4, 8, 3],“你看,这是咱村拔河比赛的对阵表!”
我定睛一看,“这……不就是个数组吗?”
“肤浅!”村长指着纸上那排数字,表情像在解说世界杯决赛,“这叫‘平衡指数’!对于每个人,我要知道他左边所有人的体重之和,与右边所有人的体重之和,差距有多大!这样我才能调整阵容,让两边势均力敌!”
我挠挠头:“……求每个位置的 |leftSum - rightSum| ?”
“对!”村长猛拍大腿,“就是这个意思!赶紧帮我算,下午就要贴对阵表了!”
我把对阵表往桌上一摊,思路直白得像村口那条水泥路——先从左往右扫一遍,记下每个位置左边所有人的体重之和;再从右往左扫一遍,记下右边所有人的体重之和;最后逐个位置算差值取绝对值:
def leftRightDifference(nums):
n = len(nums)
left_sum = [0] * n
right_sum = [0] * n
# 从左到右,计算每个位置的左侧总和
for i in range(1, n):
left_sum[i] = left_sum[i - 1] + nums[i - 1]
# 从右到左,计算每个位置的右侧总和
for i in range(n - 2, -1, -1):
right_sum[i] = right_sum[i + 1] + nums[i + 1]
# 计算差值的绝对值
for i in range(n):
answer[i] = abs(left_sum[i] - right_sum[i])
return answer
村长凑过来看了一眼,表情有点复杂,就像 code review 时发现了一段能跑但让人血压升高的代码。
“小白啊,”他拍了拍桌上那张被我用掉的草稿纸,语气里透着一股“我不是心疼钱我是心疼资源”的味道,“拔河比赛有预赛、复赛、决赛三轮,每轮每个队伍你都给我开三张表——left_sum 、right_sum 、answer ——三轮下来草纸堆得比锅炉房还高。咱村的传统你忘了?!”
我愣了一下。好家伙,三个数组一字排开,每个数组都要从头填到尾,内存占用都快赶上一支拔河队的完整档案了。而且整个过程走完,这些数组就成了再也没人翻看的旧档案——村长心疼钱,我还心疼那多余的内存分配呢。
“节省……”我咬着笔杆,盯着那三个数组开始琢磨。left_sum 好办——用一个 left 变量一路滚到底就行。从最左边往右走,走哪儿加哪儿,根本不用开数组,一个变量搞定。但 right_sum 怎么办?右边队员的体重和,在从左往右走的时候是未知的——还没走到右边呢,怎么知道右边那群人加起来多重?除非我先算一遍总和。
总和!我一个激灵,在草稿纸上划拉起来:设全队总重 total = sum(nums),对于位置 i,左边的体重和是 left,当前这个人自己的体重是 nums[i],那右边的和right不就是 total - left - nums[i] 吗?
answer[i] = |left - right|right = total - left - nums[i]answer[i] = |left - (total - left - nums[i])| = |2 * left + nums[i] - total|
我整理了下思路:left_sum 用一个滚动的变量 left 取代,right_sum 用 total - left - nums[i] 表达式消解,answer 干脆直接写回原数组 nums,连额外空间都省了。代码从三循环三数组,缩成一趟遍历原地修改:
def leftRightDifference(nums):
total = sum(nums) # 全队总体重
left = 0 # 左边已经算过的人总体重,初始为 0
for i, num in enumerate(nums):
nums[i] = abs(left * 2 + num - total) # 计算差值,直接写回原数组
left += num # 把当前人算到左边的队伍里
return nums
时间复杂度 O(n),空间复杂度 O(1)(不算答案数组的话),是真正的"原地算法"!
“三张表变零张,好啊!连草纸钱都省了!这才是咱们村的作风!” 村长高兴地直拍大腿,那兴奋劲儿比他自己拔赢了比赛还夸张。
老头把优化后的对阵表往怀里一揣,乐呵呵地走了。临出门又回头喊了一嗓子,“省下来的钱,回头给你加个鸡腿!我先去排兵布阵,下午预赛,记得来操场看拔河!”
门关上,我把拨火棍往锅炉边一靠,打开魔法书给 2574 也留了行记录:
2574 - 左右元素和的差值 解法:total 推右边和,数学去冗余。一趟遍历原地修改,O(n) 时间,O(1) 额外空间 心得:右边和不是独立信息,是派生值。用老勇者的话说——能现场算的,就别存。

本作品采用
知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议
进行许可。