Find a number in minimum steps
Given an infinite number line from -INFINITY to +INFINITY and we are on zero. We can move n steps either side at each n’th time.
Approach 1 : Using Tree
1st time; we can move only 1 step to both ways, means -1 1;
2nd time we can move 2 steps from -1 and 1;
-1 : -3 (-1-2) 1(-1+2)
1 : -1 ( 1-2) 3(1+2)
3rd time we can move 3 steps either way from -3, 1, -1, 3
-3: -6(-3-3) 0(-3+3)
1: -2(1-3) 4(1+3)
-1: -4(-1-3) 2(-1+3)
3: 0(0-3) 6(3+3)
Find the minimum number of steps to reach a given number n.
Examples:
Input : n = 10
Output : 4
We can reach 10 in 4 steps, 1, 3, 6, 10
Input : n = 13
Output : 5
We can reach 10 in 4 steps, -1, 2, 5, 9, 14
This problem can be modeled as tree. We put initial point 0 at root, 1 and -1 as children of root. Next level contains values at distance 2 and so on.
0
/ \
-1 1
/ \ / \
1 -3 -1 3
/ \ / \ / \ / \
The problem is now to find the closes node to root with value n. The idea is to do Level Order Traversal of tree to find the closest node. Note that using DFS for closest node is never a good idea (we may end up going down many unnecessary levels).
Below is C++, Python implementation of above idea.
C++
#include <bits/stdc++.h>
using namespace std;
#define InF 99999
struct number {
int no;
int level;
public :
number() {}
number( int n, int l)
: no(n), level(l)
{
}
};
void findnthnumber( int n)
{
queue<number> q;
struct number r(0, 1);
q.push(r);
while (!q.empty()) {
struct number temp = q.front();
q.pop();
if (temp.no >= InF || temp.no <= -InF)
break ;
if (temp.no == n) {
cout << "Found number n at level "
<< temp.level - 1;
break ;
}
q.push(number(temp.no + temp.level, temp.level + 1));
q.push(number(temp.no - temp.level, temp.level + 1));
}
}
int main()
{
findnthnumber(13);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static final int InF = 99999 ;
static class number
{
int no;
int level;
number() {}
number( int n, int l)
{
this .no = n;
this .level = l;
}
};
static void findnthnumber( int n)
{
Queue<number> q = new LinkedList<>();
number r = new number( 0 , 1 );
q.add(r);
while (!q.isEmpty())
{
number temp = q.peek();
q.remove();
if (temp.no >= InF || temp.no <= -InF)
break ;
if (temp.no == n)
{
System.out.print( "Found number n at level "
+ (temp.level - 1 ));
break ;
}
q.add( new number(temp.no + temp.level, temp.level + 1 ));
q.add( new number(temp.no - temp.level, temp.level + 1 ));
}
}
public static void main(String[] args)
{
findnthnumber( 13 );
}
}
|
Python3
from collections import deque
InF = 99999
class number:
def __init__( self ,n,l):
self .no = n
self .level = l
def findnthnumber(n):
q = deque()
r = number( 0 , 1 )
q.append(r)
while ( len (q) > 0 ):
temp = q.popleft()
if (temp.no > = InF or temp.no < = - InF):
break
if (temp.no = = n):
print ( "Found number n at level" , temp.level - 1 )
break
q.append(number(temp.no + temp.level, temp.level + 1 ))
q.append(number(temp.no - temp.level, temp.level + 1 ))
if __name__ = = '__main__' :
findnthnumber( 13 )
|
C#
using System;
using System.Collections.Generic;
public
class GFG
{
static readonly int InF = 99999;
public
class number
{
public
int no;
public
int level;
public
number() {}
public
number( int n, int l)
{
this .no = n;
this .level = l;
}
};
static void findnthnumber( int n)
{
Queue<number> q = new Queue<number>();
number r = new number(0, 1);
q.Enqueue(r);
while (q.Count != 0)
{
number temp = q.Peek();
q.Dequeue();
if (temp.no >= InF || temp.no <= -InF)
break ;
if (temp.no == n)
{
Console.Write( "Found number n at level "
+ (temp.level - 1));
break ;
}
q.Enqueue( new number(temp.no + temp.level, temp.level + 1));
q.Enqueue( new number(temp.no - temp.level, temp.level + 1));
}
}
public static void Main(String[] args)
{
findnthnumber(13);
}
}
|
Javascript
<script>
var InF = 99999;
class number
{
constructor(n, l)
{
this .no = n;
this .level = l;
}
};
function findnthnumber(n)
{
var q = [];
var r = new number(0, 1);
q.push(r);
while (q.length != 0)
{
var temp = q[0];
q.shift();
if (temp.no >= InF || temp.no <= -InF)
break ;
if (temp.no == n)
{
document.write( "Found number n at level "
+ (temp.level - 1));
break ;
}
q.push( new number(temp.no + temp.level, temp.level + 1));
q.push( new number(temp.no - temp.level, temp.level + 1));
}
}
findnthnumber(13);
</script>
|
Output
Found number n at level 5
Time Complexity: O(n)
Space Complexity: O(n)
The above solution is contributed by Mu Ven.
Approach 2 : Using Vector
The above solution uses binary tree for nth time instance i.e. -n and n. But as the level of tree increases this becomes inefficient. For values like abs(200) or more above program gives segmentation fault.
Below solution does not make a tree and takes complexity equal to exact number of steps required. Also the steps required are printed in the array which equals the exact sum required.
Main Idea:
- Distance between +n and -n is 2*n. So if you negate a number from +ve to -ve it will create difference of 2*n from previous sum.
- If a number lies between n(n+1)/2 and (n+1)(n+2)/2 for any n then we go to step (n+1)(n+2)/2 and try to decrease the sum to the difference using idea discussed above.
- If we go to n(n+1)/2 and then try to increase than it will ultimately lead you to same number of steps.
And since you cannot negate any number (as sum is already less than required sum) from n(n+1)/2 this proves that it takes minimum number of steps.
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > find( int n)
{
vector< int > ans;
int sum = 0;
int i;
int sign = (n >= 0 ? 1 : -1);
n = abs (n);
for (i = 1; sum < n; i++) {
ans.push_back(sign * i);
sum += i;
}
if (sum > sign * n) {
if (i % 2) {
sum -= n;
if (sum % 2) {
ans.push_back(sign * i);
sum += i++;
}
ans[(sum / 2) - 1] *= -1;
}
else {
sum -= n;
if (sum % 2) {
sum--;
ans.push_back(sign * i);
ans.push_back(sign * -1 * (i + 1));
}
ans[(sum / 2) - 1] *= -1;
}
}
return ans;
}
int main()
{
int n = 20;
if (n == 0)
cout << "Minimum number of Steps: 0\nStep sequence:\n0" ;
else {
vector< int > a = find(n);
cout << "Minimum number of Steps: " << a.size() << "\nStep sequence:\n" ;
for ( int i : a)
cout << i << " " ;
}
return 0;
}
|
Java
import java.util.*;
class GFG
{
static Vector<Integer> find( int n)
{
Vector<Integer> ans = new Vector<>();
int sum = 0 ;
int i = 1 ;
int sign = (n >= 0 ? 1 : - 1 );
n = Math.abs(n);
for (; sum < n;)
{
ans.add(sign * i);
sum += i;
i++;
}
if (sum > sign * n)
{
if (i % 2 != 0 )
{
sum -= n;
if (sum % 2 != 0 )
{
ans.add(sign * i);
sum += i;
i++;
}
int a = ans.get((sum / 2 ) - 1 );
ans.remove((sum / 2 ) - 1 );
ans.add(((sum / 2 ) - 1 ), a*(- 1 ));
}
else
{
sum -= n;
if (sum % 2 != 0 )
{
sum--;
ans.add(sign * i);
ans.add(sign * - 1 * (i + 1 ));
}
ans.add((sum / 2 ) - 1 , ans.get((sum / 2 ) - 1 ) * - 1 );
}
}
return ans;
}
public static void main(String[] args)
{
int n = 20 ;
if (n == 0 )
System.out.print( "Minimum number of Steps: 0\nStep sequence:\n0" );
else
{
Vector<Integer> a = find(n);
System.out.print( "Minimum number of Steps: " +
a.size()+ "\nStep sequence:\n" );
for ( int i : a)
System.out.print(i + " " );
}
}
}
|
Python3
def find(n):
ans = []
Sum = 0
i = 0
sign = 0
if (n > = 0 ):
sign = 1
else :
sign = - 1
n = abs (n)
i = 1
while ( Sum < n):
ans.append(sign * i)
Sum + = i
i + = 1
if ( Sum > sign * n):
if (i % 2 ! = 0 ):
Sum - = n
if ( Sum % 2 ! = 0 ):
ans.append(sign * i)
Sum + = i
i + = 1
ans[ int ( Sum / 2 ) - 1 ] * = - 1
else :
Sum - = n
if ( Sum % 2 ! = 0 ):
Sum - = 1
ans.append(sign * i)
ans.append(sign * - 1 * (i + 1 ))
ans[ int (( sum / 2 )) - 1 ] * = - 1
return ans
n = 20
if (n = = 0 ):
print ( "Minimum number of Steps: 0\nStep sequence:\n0" )
else :
a = find(n)
print ( "Minimum number of Steps:" , len (a))
print ( "Step sequence:" )
print ( * a, sep = " " )
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static List< int > find( int n)
{
List< int > ans = new List< int >();
int sum = 0;
int i = 1;
int sign = (n >= 0 ? 1 : -1);
n = Math.Abs(n);
for (; sum < n;)
{
ans.Add(sign * i);
sum += i;
i++;
}
if (sum > sign * n)
{
if (i % 2 != 0)
{
sum -= n;
if (sum % 2 != 0)
{
ans.Add(sign * i);
sum += i;
i++;
}
int a = ans[((sum / 2) - 1)];
ans.RemoveAt((sum / 2) - 1);
ans.Insert(((sum / 2) - 1), a*(-1));
}
else
{
sum -= n;
if (sum % 2 != 0)
{
sum--;
ans.Add(sign * i);
ans.Add(sign * -1 * (i + 1));
}
ans.Insert((sum / 2) - 1, ans[(sum / 2) - 1] * -1);
}
}
return ans;
}
public static void Main(String[] args)
{
int n = 20;
if (n == 0)
Console.Write( "Minimum number of Steps: 0\nStep sequence:\n0" );
else
{
List< int > a = find(n);
Console.Write( "Minimum number of Steps: " +
a.Count+ "\nStep sequence:\n" );
foreach ( int i in a)
Console.Write(i + " " );
}
}
}
|
Javascript
<script>
function find(n)
{
let ans = [];
let sum = 0;
let i = 1;
let sign = (n >= 0 ? 1 : -1);
n = Math.abs(n);
for (; sum < n;)
{
ans.push(sign * i);
sum += i;
i++;
}
if (sum > sign * n)
{
if (i % 2 != 0)
{
sum -= n;
if (sum % 2 != 0)
{
ans.push(sign * i);
sum += i;
i++;
}
ans[parseInt(sum / 2, 10) - 1] =
ans[parseInt(sum / 2, 10) - 1]*(-1);
}
else
{
sum -= n;
if (sum % 2 != 0)
{
sum--;
ans.push(sign * i);
ans.push(sign * -1 * (i + 1));
}
ans[parseInt(sum / 2, 10) - 1] =
ans[parseInt(sum / 2, 10) - 1] * -1;
}
}
return ans;
}
let n = 20;
if (n == 0)
document.write( "Minimum number of Steps: 0" +
"</br>" + "Step sequence:" + "</br>" + "0" );
else
{
let a = find(n);
document.write( "Minimum number of Steps: " +
a.length + "</br>" + "Step sequence:" +
"</br>" );
for (let i = 0; i < a.length; i++)
document.write(a[i] + " " );
}
</script>
|
Output
Minimum number of Steps: 7
Step sequence:
1 2 3 -4 5 6 7
If n is the sum that it is required and s is the minimum steps then:
n = (s+1)*(s+2)/2 + 1 (or +2)
Hence n = O(s*s)
Therefore s = O(sqrt(n))
Space Complexity : O(sqrt(n))
Time complexity : O(sqrt(n))
Last Updated :
20 Feb, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...