Find Closest Number to Zero
Find Closest Number to Zero: given an integer array nums, return the value with the smallest absolute value, breaking ties in favour of the larger (positive) number.
- 1 <= nums.length <= 1000
- -10⁵ <= nums[i] <= 10⁵
Intuition
Distance from zero is just abs(x), so the answer is the element minimising it — a single scan tracking the best candidate. The only subtlety is the tie-break: -3 and 3 sit the same distance out, and the problem asks for 3. Fold that rule directly into the comparison instead of post-processing, and one pass with two variables settles it.
Any closest to a target phrasing is a minimum over abs(x - target), solvable in one pass. When the statement adds a tie-break rule, encode it as the second clause of the same comparison instead of a cleanup pass. The same shape appears in Find K Closest Elements and Minimum Absolute Difference.
Approach
Before reading on: write the comparison that decides whether a new number replaces the current best. Make sure it returns 3 rather than -3 for [-3, 3], and think about what goes wrong if you seed the answer with 0.
Turn the question into a minimum over a key
The phrase closest to zero is a distance, and on the integer line the distance from x to 0 is abs(x). That converts the problem into a plain minimum-finding scan, keyed on abs(x) rather than on x itself. Keep one variable best holding the winning value so far; for each element compare abs(num) against abs(best) and replace when it is strictly smaller. Nothing about the array needs to be sorted or preprocessed, because a minimum is discoverable in one linear sweep.
The tie-break is the whole problem
When abs(num) == abs(best) the two candidates are equidistant, which happens exactly when they are negatives of each other, such as -2 and 2. The specification says return the larger, so add num > best as the second half of the replacement test. Writing the condition as abs(num) < abs(best) or (abs(num) == abs(best) and num > best) covers both cases in one expression. A common shortcut — scanning for the minimum absolute value first and then picking its sign afterwards — needs a second pass and still has to resolve the tie, so folding it in is both shorter and cheaper.
Seeding the scan safely
Initialise best to the first element rather than to a sentinel like 0 or infinity. Seeding with 0 is wrong outright: zero beats every other value on distance, so the function would return 0 for an array that never contains it. Infinity works for the distance but leaves best as a non-integer that the tie-break num > best cannot compare meaningfully. The constraints guarantee at least one element, so nums[0] is always available and is the honest starting point. The loop then runs over the remaining elements, giving O(n) time and O(1) space.
Solution & live demo
Common pitfalls
Seeding best with 0
best = 0
for num in nums:
if abs(num) < abs(best):
best = numbest = nums[0]
for num in nums[1:]:
...abs(0) is 0, which no element can beat, so the loop never replaces the seed and the function returns 0 for arrays like [4, -2] that contain no zero at all.
Ignoring the tie-break
if abs(num) < abs(best):
best = numif abs(num) < abs(best) or (abs(num) == abs(best) and num > best):
best = numOn [-3, 3] the strict < never fires for the second element, so -3 is returned. The problem explicitly requires the larger value when distances tie.
Comparing values instead of distances
if num < best:
best = numif abs(num) < abs(best):
best = numThis finds the array minimum, not the closest to zero. On [-9, 2] it returns -9, which is the furthest element from zero rather than the nearest.
Edge cases
The seed is the answer; the loop body never runs.
Equal distance, so the tie-break returns the positive 2.
Zero has distance 0, which nothing can beat, so it wins.
No tie arises; -3 has the smallest absolute value and wins.
The strict < and > comparisons leave the first 4 in place, which is the same value anyway.