Reach a Number
MedPrompt
You are standing at position 0 on an infinite number line. There is a destination at position target.
You can make some number of moves numMoves so that:
- On each move, you can either go left or right.
- During the
ithmove (starting fromi == 1toi == numMoves), you takeisteps in the chosen direction.
Given the integer target, return the minimum number of moves required (i.e., the minimum numMoves) to reach the destination.
Example 1:
Input: target = 2
Output: 3
Explanation:
On the 1st move, we step from 0 to 1 (1 step).
On the 2nd move, we step from 1 to -1 (2 steps).
On the 3rd move, we step from -1 to 2 (3 steps).Example 2:
Input: target = 3
Output: 2
Explanation:
On the 1st move, we step from 0 to 1 (1 step).
On the 2nd move, we step from 1 to 3 (2 steps).
Constraints:
-109 <= target <= 109target != 0
Approaches
3 approaches with complexity analysis and trade-offs.
This approach models the problem as a state-space search. A state is defined by the current position on the number line. We start at position 0 and perform a Breadth-First Search (BFS) to explore all possible positions reachable with an increasing number of moves. Each level in the BFS corresponds to one additional move. The first time we land on the target position, we have found the minimum number of moves required, as BFS naturally explores the search space layer by layer.
Algorithm
- Initialize a queue
qwith the starting position0. - Initialize
moves = 0. - Start a loop that continues as long as the queue is not empty.
- Inside the loop, increment
movesto represent the current move number. - Process all nodes at the current level of the BFS. Get the queue size
levelSizebefore starting the inner loop. - For each of the
levelSizeelements in the queue:- Dequeue the
currentPos. - Calculate the two possible next positions:
pos1 = currentPos + movesandpos2 = currentPos - moves. - If either
pos1orpos2equals thetarget, we have found the minimum number of moves, so returnmoves. - To avoid redundant exploration in the next level, add
pos1andpos2to aSetfor the next level's positions.
- Dequeue the
- After processing all nodes at the current level, add all unique positions from the
Setinto the main queueq. - This process guarantees finding the shortest path in terms of the number of moves.
Walkthrough
We use a queue to manage the positions to visit, starting with 0. We iterate level by level, where each level k corresponds to making the k-th move. For every position p reached after k-1 moves, we explore the two new positions p+k and p-k. If either of these is the target, we've found our answer, k. To manage the exponentially growing number of states, we can use a Set to store the unique positions for the next level, preventing duplicate states in the queue for the same level. However, due to the enormous state space (2^k states at level k), this approach is not feasible for the given constraints where target can be large, leading to a large number of required moves.
import java.util.HashSet;import java.util.LinkedList;import java.util.Queue;import java.util.Set; class Solution { public int reachNumber(int target) { // This approach is too slow and will cause TLE/MLE. // It is for demonstration of a brute-force method. Queue<Long> queue = new LinkedList<>(); queue.add(0L); int moves = 0; while (!queue.isEmpty()) { moves++; int levelSize = queue.size(); Set<Long> nextLevelPositions = new HashSet<>(); for (int i = 0; i < levelSize; i++) { long currentPos = queue.poll(); long pos1 = currentPos + moves; if (pos1 == target) { return moves; } nextLevelPositions.add(pos1); long pos2 = currentPos - moves; if (pos2 == target) { return moves; } nextLevelPositions.add(pos2); } // This check is to prune the search space, but it's still too large. if (nextLevelPositions.size() > 50000) { // Heuristic to stop TLE in platforms, but the approach is flawed. // A proper solution would not need this. break; } queue.addAll(nextLevelPositions); } return -1; // Should not be reached with a correct algorithm }}Complexity
Time
O(2^k), where k is the minimum number of moves. We explore an exponentially growing number of states.
Space
O(2^k), where k is the minimum number of moves. The queue can hold up to O(2^k) distinct positions at level k.
Trade-offs
Pros
Conceptually simple and easy to understand.
Guaranteed to find the minimum number of moves if it could run to completion.
Cons
Extremely inefficient in terms of both time and memory.
The number of possible positions to check grows exponentially with the number of moves (
2^k).Will result in Time Limit Exceeded (TLE) and Memory Limit Exceeded (MLE) for the given constraints.
This approach moves away from brute-force and uses a mathematical insight. The problem is symmetric, so reaching target or -target takes the same number of moves. We can therefore assume target is positive. The core idea is to find the smallest number of moves, k, such that the sum of steps S = 1 + 2 + ... + k is not only greater than or equal to target, but also S - target is an even number. This even difference ensures that we can change the sign of some moves (which changes the sum by an even amount) to land exactly on target.
Algorithm
- First, handle the symmetry of the problem by taking the absolute value of the target:
target = Math.abs(target). - Initialize the number of moves
k = 0and the cumulative sum of stepssum = 0. - Find the smallest
ksuch that the sum of all positive stepssum = 1 + 2 + ... + kis greater than or equal totarget. This is done with a loop:while (sum < target):k++sum += k
- At this point,
sum >= target. Calculate the differencedelta = sum - target. - The key insight is that
deltamust be an even number. This is because flipping any moveifrom+ito-ichanges the total sum by-2i, which is an even number. Therefore, to reducesumtotarget, the difference must be a multiple of 2. - If
deltais not even, we must take more steps. We continue incrementingkand adding it tosumuntil(sum - target)is even.while ((sum - target) % 2 != 0):k++sum += k
- The final value of
kis the minimum number of moves required. This second loop will execute at most twice.
Walkthrough
We start by making target positive. Then, we iteratively find the smallest k such that the sum of steps from 1 to k (sum) is at least target. This gives us a potential number of moves. We then check the difference delta = sum - target. If delta is even, we can always find a combination of moves to flip (from + to -) to reduce the sum by exactly delta, so k is our answer. If delta is odd, we can't reach the target with k moves. We must take more moves. We increment k and update sum until sum - target becomes even. This process is guaranteed to terminate quickly (in at most two additional steps) because adding k+1 and then k+2 will change the parity of the difference correctly.
class Solution { public int reachNumber(int target) { target = Math.abs(target); int k = 0; long sum = 0; while (sum < target) { k++; sum += k; } while ((sum - target) % 2 != 0) { k++; sum += k; } return k; }}Complexity
Time
O(sqrt(target)). The first loop runs until `k*(k+1)/2 >= target`, which means `k` is proportional to `sqrt(target)`. The second loop runs at most twice.
Space
O(1), as we only use a few variables to store the state (`k`, `sum`).
Trade-offs
Pros
Very efficient compared to the brute-force approach.
Simple and intuitive to implement.
Constant space complexity.
Cons
Involves a loop that depends on the magnitude of
target, making it slightly less performant than a pure O(1) formulaic solution.
This is the most optimal solution, which refines the iterative mathematical approach by replacing the initial loop with a direct analytical formula. It calculates the minimum k such that the sum of steps 1 + ... + k surpasses the target in constant time. After finding this initial k, it uses the same parity-based logic to determine if k, k+1, or k+2 is the correct answer, resulting in an overall constant time solution.
Algorithm
- Take the absolute value of the target:
target = Math.abs(target). - Directly calculate the smallest integer
kthat satisfiesk*(k+1)/2 >= target. This can be found by solving the quadratic equationk^2 + k - 2*target = 0forkand taking the ceiling of the positive root. The formula isk = ceil((-1 + sqrt(1 + 8*target)) / 2). - Calculate the sum for this
k:sum = k*(k+1)/2. - Find the difference:
delta = sum - target. - If
deltais even (delta % 2 == 0), thenkis the minimum number of moves. Returnk. - If
deltais odd, we need more moves. We check the parity ofk:- If
kis even, the next movek+1is odd. The new differencedelta + (k+1)will beodd + odd = even. So, the answer isk+1. - If
kis odd, the next movek+1is even. The new differencedelta + (k+1)will beodd + even = odd. We need one more move. The subsequent movek+2is odd. The total differencedelta + (k+1) + (k+2)will beodd + even + odd = even. So, the answer isk+2.
- If
Walkthrough
The foundation of this approach is identical to the previous one: find the smallest k such that sum = k*(k+1)/2 >= target and sum - target is even. Instead of looping to find k, we solve the inequality k^2 + k - 2*target >= 0 directly. The positive root is (-1 + sqrt(1 + 8*target))/2. The smallest integer k is the ceiling of this value. Once k is found, we calculate sum and delta = sum - target. If delta is even, k is the answer. If delta is odd, we know we need more steps. A simple analysis of parity shows that if k is even, k+1 moves will suffice. If k is odd, k+2 moves are required. This allows us to find the answer with a few calculations, completely avoiding loops.
class Solution { public int reachNumber(int target) { target = Math.abs(target); // We need k such that k*(k+1)/2 >= target // k^2 + k - 2*target >= 0 // Using quadratic formula, the positive root is (-1 + sqrt(1 + 8*target))/2 // Our k is the ceiling of this value. long k = (long) Math.ceil((-1.0 + Math.sqrt(1.0 + 8.0 * target)) / 2.0); long sum = k * (k + 1) / 2; long delta = sum - target; if (delta % 2 == 0) { return (int) k; } else { // If delta is odd, we need more steps. // If k is even, k+1 is odd. sum becomes sum+k+1. delta becomes delta+k+1 (odd+odd=even). So k+1 steps. // If k is odd, k+1 is even. delta becomes delta+k+1 (odd+even=odd). We need one more step. // The next step k+2 is odd. delta becomes delta+k+1+k+2 (odd+even+odd=even). So k+2 steps. if (k % 2 == 0) { // k+1 is odd return (int) (k + 1); } else { // k is odd return (int) (k + 2); } } }}Complexity
Time
O(1), as it involves a fixed number of arithmetic operations, including `sqrt`, which is considered constant time for practical purposes.
Space
O(1), as it only uses a fixed number of variables for calculation.
Trade-offs
Pros
Extremely efficient, providing a solution in constant time.
Optimal in terms of both time and space complexity.
Cons
The mathematical formula might be less intuitive to derive than the iterative solution.
Requires careful handling of floating-point arithmetic and conversion to integers.
Solutions
Solution
class Solution {public int reachNumber(int target) { target = Math.abs(target); int s = 0, k = 0; while (true) { if (s >= target && (s - target) % 2 == 0) { return k; } ++k; s += k; } }}/** * @param {number} target * @return {number} */ var reachNumber = function ( target ) { target = Math . abs ( target ); let [ s , k ] = [ 0 , 0 ]; while ( 1 ) { if ( s >= target && ( s - target ) % 2 == 0 ) { return k ; } ++ k ; s += k ; } };class Solution {public: int reachNumber(int target) { target = abs(target); int s = 0, k = 0; while (1) { if (s >= target && (s - target) % 2 == 0) return k; ++k; s += k; } }};class Solution: def reachNumber(self, target: int) -> int: target = abs(target) s = k = 0 while 1: if s >= target and (s - target) % 2 == 0: return k k += 1 s += kVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.