Topic: Learning notes
LeetCode 2574: Left and Right Sum Differences in TypeScript
Compare stored left and right sums with a single scan, including output space, auxiliary space, and the loop invariant.
This note starts with an implementation I wrote, then uses AI to review the derivation and test cases. Before publishing, I checked the program behavior, complexity, and problem constraints again.
Problem
Original problem: LeetCode 2574: Left and Right Sum Differences
Given an integer array nums, let leftSum[i] be the sum strictly left of index i, and let rightSum[i] be the sum strictly right of it. Return answer, where answer[i] = |leftSum[i] - rightSum[i]|. A missing side has a sum of 0.
For example, [10, 4, 8, 3] becomes [15, 1, 11, 22].
The original code was correct, but kept intermediate arrays it did not need
The original code builds every left sum and right sum before producing the answer.
function leftRightDifference(nums: number[]): number[] {
const total = nums.reduce((sum, num) => sum + num, 0);
const leftSum = [0];
const rightSum = [total - nums[0]];
for (let index = 1; index < nums.length; index += 1) {
leftSum.push(leftSum[index - 1] + nums[index - 1]);
rightSum.push(total - nums[index] - leftSum[index]);
}
const answer: number[] = [];
for (let index = 0; index < leftSum.length; index += 1) {
answer.push(Math.abs(leftSum[index] - rightSum[index]));
}
return answer;
}
This returns the correct answer. leftSum[0] is 0, rightSum[0] is the sum to the right of the first value, and each later position follows the same definition.
The cost is storage. The code retains leftSum, rightSum, and answer. Its three linear passes are still O(n) time, but even when the returned answer is excluded, the two intermediate arrays make auxiliary space O(n). The problem only needs the final difference at each index, so it does not need both full arrays.
nums[0] assumes at least one input value, which matches the original constraints. A general-purpose helper would need to define behavior for an empty array.
Better version: remove the current value from the right first
Start with the total. For each value, remove it from the right sum, record the difference, then add it to the left sum. Both variables match the problem definition at the point where the answer is written.
function leftRightDifference(nums: number[]): number[] {
const answer: number[] = [];
let leftSum = 0;
let rightSum = nums.reduce((sum, num) => sum + num, 0);
for (const num of nums) {
rightSum -= num;
answer.push(Math.abs(leftSum - rightSum));
leftSum += num;
}
return answer;
}
Another common implementation adds num to leftSum, records the difference, and only then subtracts it from rightSum. That also works because both sides include the same num, which cancels in the subtraction. Removing from the right first and adding to the left last makes the variable names match their meaning without relying on that cancellation. console.log() is useful while debugging but should not remain in the final solution.
Why the loop is correct
Before each num, leftSum equals the sum of processed values, while rightSum equals the sum of the unprocessed values including num.
After rightSum -= num, it is exactly the sum strictly to the right of the current value. leftSum is still the sum strictly to the left, so the stored absolute difference satisfies the definition of the current result. Adding num to leftSum restores the invariant for the next iteration. Every value is processed once, so every result is correct.
Minimal verification
import assert from "node:assert/strict";
assert.deepStrictEqual(leftRightDifference([10, 4, 8, 3]), [15, 1, 11, 22]);
assert.deepStrictEqual(leftRightDifference([1]), [0]);
assert.deepStrictEqual(leftRightDifference([5, -2, 4]), [2, 1, 3]);
The final case confirms that negative values follow the same sum and absolute-difference rules.
Complexity and transferable idea
reduce() visits the values once and the loop visits them once, so time is O(n). The returned answer needs O(n) storage. If the analysis asks for auxiliary working space, this version uses two scalar variables and needs O(1).
The original leftSum and rightSum arrays are useful when later operations need to query many stored prefixes or suffixes. This problem writes one final answer per index, so keeping them only increases memory use.
Common mistakes
- Including or excluding the current value on both sides without checking whether the formula cancels it.
- Accessing
nums[0]without first establishing its input assumption. - Mixing returned storage with auxiliary working space.
- Using
console.log()instead of an assertion that fails on a wrong result.
External references
- LeetCode 2574: Left and Right Sum Differences: original problem, examples, and constraints.
- TypeScript Handbook: More on Functions: function parameter and return-type syntax.
- Node.js: assert.deepStrictEqual(): assertions for array results.