Given an infinite number line. We start at 0 and can go either to the left or to the right. The condition is that in the ith move, you must take i steps. Given a destination d, the task is to find the minimum number of steps required to reach that destination.
Examples:
Input: d = 2
Output: 3
Explanation: The steps taken are +1, -2 and +3.Input: d = 10
Output: 4
Explanation: The steps taken are +1, +2, +3 and +4.
Table of Content
[Naive Approach] Using Recursion - O( 2 ^ n) Time and O(d) Space
We can always reach any destination as it is always possible to make a move of length 1. At any step i, we can move forward i, then backward i + 1. Since the distance of +5 and -5 from 0 is the same, hence we find the answer for the absolute value of the destination. The idea is to recursively explore both left and right movements on a number line.
- Starting from the origin (0), we recursively call for both movements with incremented number of steps and changed current position.
- If the absolute value of the current position exceeds the destination, the path is considered invalid, and the function returns a large value.
- If the current position matches the destination, the number of steps taken is returned.
// C++ program to find Minimum steps to reach a destination
// using recursion
#include <bits/stdc++.h>
using namespace std;
int minRecur(int curr, int steps, int d) {
// This ensures this path is not
// considered for minimum steps
if (abs(curr) > d) return INT_MAX;
if (curr == d) return steps;
// Recursively explore left movement
int left = minRecur(curr-steps-1, steps+1, d);
// Recursively explore right movement
int right = minRecur(curr+steps+1, steps+1, d);
// Return the minimum steps path
// between left and right movements
return min(left, right);
}
int minSteps(int d) {
// Convert destination to positive distance
d = abs(d);
return minRecur(0, 0, d);
}
int main() {
int d = 2;
cout << minSteps(d);
return 0;
}
import java.lang.Math;
class GfG {
static int minRecur(int curr, int steps, int d) {
// This ensures this path is not
// considered for minimum steps
if (Math.abs(curr) > d) return Integer.MAX_VALUE;
if (curr == d) return steps;
// Recursively explore left movement
int left = minRecur(curr - steps - 1, steps + 1, d);
// Recursively explore right movement
int right = minRecur(curr + steps + 1, steps + 1, d);
// Return the minimum steps path
// between left and right movements
return Math.min(left, right);
}
static int minSteps(int d) {
// Convert destination to positive distance
d = Math.abs(d);
return minRecur(0, 0, d);
}
public static void main(String[] args) {
int d = 2;
System.out.println(minSteps(d));
}
}
import sys
def minRecur(curr, steps, d):
# This ensures this path is not
# considered for minimum steps
if abs(curr) > d:
return sys.maxsize
if curr == d:
return steps
# Recursively explore left movement
left = minRecur(curr - steps - 1, steps + 1, d)
# Recursively explore right movement
right = minRecur(curr + steps + 1, steps + 1, d)
# Return the minimum steps path
# between left and right movements
return min(left, right)
def minSteps(d):
# Convert destination to positive distance
d = abs(d)
return minRecur(0, 0, d)
if __name__ == "__main__":
d = 2
print(minSteps(d))
using System;
class GfG {
static int minRecur(int curr, int steps, int d) {
// This ensures this path is not
// considered for minimum steps
if (Math.Abs(curr) > d) return int.MaxValue;
if (curr == d) return steps;
// Recursively explore left movement
int left = minRecur(curr - steps - 1, steps + 1, d);
// Recursively explore right movement
int right = minRecur(curr + steps + 1, steps + 1, d);
// Return the minimum steps path
// between left and right movements
return Math.Min(left, right);
}
static int minSteps(int d) {
// Convert destination to positive distance
d = Math.Abs(d);
return minRecur(0, 0, d);
}
static void Main(string[] args) {
int d = 2;
Console.WriteLine(minSteps(d));
}
}
function minRecur(curr, steps, d) {
// This ensures this path is not
// considered for minimum steps
if (Math.abs(curr) > d) return Number.MAX_SAFE_INTEGER;
if (curr === d) return steps;
// Recursively explore left movement
const left = minRecur(curr - steps - 1, steps + 1, d);
// Recursively explore right movement
const right = minRecur(curr + steps + 1, steps + 1, d);
// Return the minimum steps path
// between left and right movements
return Math.min(left, right);
}
function minSteps(d) {
// Convert destination to positive distance
d = Math.abs(d);
return minRecur(0, 0, d);
}
let d = 2;
console.log(minSteps(d));
Output
3
[Efficient Approach] Using Even/Odd Parity - O(n) Time and O(1) Space
We find the answer for the absolute value of the destination as steps would be the same. Starting from zero, we incrementally increase our steps, with each move allowing us to move a number of steps equal to the current move number. We continue moving forward, accumulating steps until we either reach or overshoot the target. The key complexity arises when we overshoot the target, which requires a adjustment of our moves:
Even Difference Scenario: When the total accumulated distance differs from the target by an even number, we can resolve this by flipping the sign of a specific move.
Example: Moves: 1 2 3 4 5 6 (total 21), target = 19
- Difference is 2 (even)
- We can flip 1 to -1, transforming the sequence to -1 2 3 4 5 6
- This exactly reaches the target of 19
Odd Difference Scenario: When the difference is odd, we continue adding moves until we can create an even difference, which allows us to perform a strategic move-flipping adjustment.
Example: Moves 1 2 3 4 5 6 (total 21), target 20
- Difference is 1 (odd)
- We add another move (7), new total becomes 28
- Difference is now 8 (even)
- We can now flip 4th move to reach exactly 20, i.e., 1 2 3 -4 5 6 7
#include <iostream>
using namespace std;
int minSteps(int d) {
// Handling negatives by symmetry
d = abs(d);
// Keep moving while sum is
// smaller or difference is odd.
int sum = 0, step = 0;
while (sum < d || (sum - d) % 2 != 0) {
step++;
sum += step;
}
return step;
}
int main() {
int d = 2;
cout << minSteps(d);
return 0;
}
class GfG {
static int minSteps(int d) {
// Handling negatives by symmetry
d = Math.abs(d);
// Keep moving while sum is
// smaller or difference is odd.
int sum = 0, step = 0;
while (sum < d || (sum - d) % 2 != 0) {
step++;
sum += step;
}
return step;
}
public static void main(String[] args) {
int d = 2;
System.out.println(minSteps(d));
}
}
def minSteps(d):
# Handling negatives by symmetry
d = abs(d)
# Keep moving while sum is
# smaller or difference is odd.
sum = 0
step = 0
while sum < d or (sum - d) % 2 != 0:
step += 1
sum += step
return step
if __name__ == "__main__":
d = 2
print(minSteps(d))
using System;
class GfG {
static int minSteps(int d) {
// Handling negatives by symmetry
d = Math.Abs(d);
// Keep moving while sum is
// smaller or difference is odd.
int sum = 0, step = 0;
while (sum < d || (sum - d) % 2 != 0) {
step++;
sum += step;
}
return step;
}
static void Main(string[] args) {
int d = 2;
Console.WriteLine(minSteps(d));
}
}
function minSteps(d) {
// Handling negatives by symmetry
d = Math.abs(d);
// Keep moving while sum is
// smaller or difference is odd.
let sum = 0, step = 0;
while (sum < d || (sum - d) % 2 !== 0) {
step++;
sum += step;
}
return step;
}
let d = 2;
console.log(minSteps(d));
Output
3