Skip to content
← All posts

Smallest Range I: Shrink the Gap with Math

5 min read
leetcodeproblemeasyarraysmath

You are given an integer array nums and an integer k. In one operation, you can choose any element of nums and add any value x to it where -k <= x <= k. You only get to do this once per element. Return the minimum possible difference between the maximum and minimum values of the modified array.

This is LeetCode 908: Smallest Range I, and it is one of those problems where the code is trivially short but the insight behind it is worth understanding clearly. Once you see why the formula works, you will never forget it.

nums = [1, 3, 6], k = 31i=03i=16i=2minmax0123456789min + k = 4max - k = 3Overlap! Difference = max(0, 6 - 1 - 2*3) = 0
Each element can shift by up to k on the number line. Green = min moves up, yellow = max moves down. When ranges overlap, the answer is 0.

Why this problem is easier than it looks

At first glance, you might think you need to try different adjustments for each element and find the optimal combination. That sounds like it could be exponential. But take a step back and think about what you are actually trying to do.

You want to minimize the range (max - min) of the final array. You can move each element up or down by at most k. So what is the best possible strategy?

  • Increase the smallest element by as much as possible (add k to it).
  • Decrease the largest element by as much as possible (subtract k from it).

All other elements are somewhere in between, so they can always be adjusted to fit within whatever gap remains between the new min and new max.

The original gap between max and min is max(nums) - min(nums). After applying the optimal adjustments, the gap shrinks by 2k (because you add k to the bottom and subtract k from the top). If this makes the gap negative, that means you can make all elements equal, so the answer is 0.

The key insight: you only need to look at the min and max of the array. Every other element can always be adjusted to fit within the range defined by those two extremes after their optimal shifts.

The formula

The answer is a single expression:

answer = max(0, max(nums) - min(nums) - 2 * k)

That is the entire algorithm. Find the max, find the min, subtract 2k, and clamp at zero. No sorting, no iteration beyond finding the extremes.

The code

def smallestRangeI(nums, k):
    return max(0, max(nums) - min(nums) - 2 * k)

One line. Let's make sure we understand every piece of it:

  1. max(nums) - min(nums) gives you the original range of the array.
  2. Subtracting 2 * k accounts for moving the min up by k and the max down by k.
  3. The outer max(0, ...) ensures we never return a negative difference. If the ranges overlap (meaning we can make all elements equal), the answer is 0.

Walking through it step by step

Let's trace through nums = [1, 3, 6] and k = 3 to see the logic clearly.

Step 1: Find min and max of the array

Scan the array once to find the minimum and maximum values. For nums = [1, 3, 6]: min = 1, max = 6.

min(nums) = 1, max(nums) = 6

Step 2: Compute the original gap

The current difference between the largest and smallest elements is max - min. This is the range we need to shrink.

gap = max - min = 6 - 1 = 5

Step 3: Apply +k to min and -k to max

The best strategy is to increase the minimum by k (making it as large as possible) and decrease the maximum by k (making it as small as possible). This shrinks the gap by 2k total.

new gap = gap - 2k = 5 - 2*3 = -1

Step 4: Clamp at zero

The difference cannot be negative (you do not have to use the full range of k). If the gap after subtracting 2k is negative, the answer is 0 because you can make all elements equal.

answer = max(0, -1) = 0

The ranges for min and max actually overlap on the number line (min can reach 4, max can drop to 3), so we can make all elements converge. The answer is 0.

Now try nums = [0, 10] with k = 2. The gap is 10 - 0 = 10. After adjustment: 10 - 2*2 = 6. The ranges do not overlap, so the minimum possible difference is 6.

Complexity analysis

ApproachTimeSpace
Optimal (formula)O(n)O(1)

Time: O(n). We scan the array once to find the min and max. Everything else is O(1) arithmetic.

Space: O(1). We only store two values (the min and max), regardless of input size.

This is optimal. You must look at every element at least once because any element could be the min or max.

The building blocks

This problem uses one fundamental pattern:

1. Reduce to extremes. Instead of reasoning about what happens to every element, recognize that the answer depends only on the min and max. All intermediate elements are irrelevant because they can always be shifted to fit within the final range. This same "only the extremes matter" reasoning shows up in problems like Best Time to Buy and Sell Stock (where you track min price seen so far) and Maximum Subarray (where you track running max).

2. Geometric/number-line reasoning. Visualizing each element as a point on a number line, with a range of reachable values [nums[i] - k, nums[i] + k], makes the overlap condition obvious. If the reachable range of the min overlaps with the reachable range of the max, you can collapse everything to a single point.

Edge cases to watch for

  • Single element [5] with any k: the array has only one element, so max - min = 0. The answer is always 0.
  • k = 0: no adjustment allowed. The answer is simply max(nums) - min(nums).
  • All elements equal like [4, 4, 4]: max - min is already 0. The answer is 0 regardless of k.
  • k is very large: if 2k >= max - min, the answer is 0. The formula handles this via the max(0, ...) clamp.
  • Two elements far apart like [1, 100] with k = 10: answer = max(0, 100 - 1 - 20) = 79. You can shrink the gap but not eliminate it.

From understanding to recall

This problem is deceptively simple. You read the one-line solution and think "I will never forget this." But two weeks from now, when a similar problem asks about ranges or intervals, will you immediately see that only the extremes matter? Or will you get stuck trying to reason about individual elements?

Spaced repetition locks in these insights. By revisiting the "reduce to extremes" pattern at increasing intervals, you build the reflex to ask "do I really need all elements, or just the min and max?" That reflex transfers directly to harder problems involving ranges and bounds.

The pattern of collapsing a problem to a simple formula after identifying what actually matters is one of the most powerful building blocks for easy and medium array problems. Drilling it until it becomes automatic saves you minutes in interviews that you can spend on harder questions.

Related posts