题目重点:一个数x变为−x,总和从S变为S−2x,比较所有候选。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 可不翻转或翻转恰一个元素,允许负数、零和空数组;返回最小绝对值。
- 不是任选子集翻转,也不是修改数值大小。
解题路线
- 先求总和S。不翻转的成本为|S|。每个位置翻转会删除原x并加上−x,变化−2x。
- 枚举|S−2x|并取最小。若需要位置,同时保存改进下标;并列策略先约定,避免无意义地翻转零。
- 若有大量同数组不同目标查询,可对数值排序并在S/2附近二分,但单次求解全遍历更直接。
手动走一遍
[2,3,8],S=13;翻转2/3/8后绝对值9/7/3,因此答案3。[−4,1,1],S=−2;翻转任一个正1得−4更差,不翻转成本2最优。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def min_abs_sum(a):
total = sum(a)
return min([abs(total)] + [abs(total - 2 * x) for x in a])
复杂度
O(n)时间。当前简明示例建立候选列表为O(n)空间;可用生成器/循环把额外空间降O(1)。
易错点与追问
容易失分的边界
- 变化量是−2x,不是−x。
- “必须翻转一次”时空数组不可行,且不能保留不翻转候选。
继续深挖
- 返回操作位置及最终数组怎样规定并列?
- 最多翻转两数可怎样用排序双指针寻找最接近S/2的两数和?
