Given a number n. Find the minimum number of operations required to reach n starting from 0. You have two operations available:
- Double the number
- Add one to the number
Examples:
Input: n = 8
Output: 4
Explanation: 0 + 1 = 1 --> 1 + 1 = 2 --> 2 * 2 = 4 --> 4 * 2 = 8.Input: n = 7
Output: 5
Explanation: 0 + 1 = 1 --> 1 + 1 = 2 --> 1 + 2 = 3 --> 3 * 2 = 6 --> 6 + 1 = 7.
Table of Content
[Naive Approach] Using Recursion - O(2 ^ n) Time and O(n) Space
The idea is to recursively try both available operations, add 1 and double, and find the minimum number of operations required to reach n.
Working of Approach:
- Start from 0 and recursively consider both operations.
- Adding 1 increases the current value by one.
- If n is even, consider reaching n by doubling n / 2.
- Return the minimum operations among the two choices.
#include <iostream>
#include <climits>
using namespace std;
int minOperation(int n)
{
// Base case: 0 operations are needed to reach 0
if (n == 0)
return 0;
// Operation 1: reach n from n - 1
int add = minOperation(n - 1);
// Operation 2: reach n from n / 2
int dbl = INT_MAX;
if (n % 2 == 0)
dbl = minOperation(n / 2);
// Take the minimum of both choices
return 1 + min(add, dbl);
}
int main()
{
int n = 7;
cout << minOperation(n);
return 0;
}
import java.util.Arrays;
public class GFG {
// Function to find minimum operations
static int minOperation(int n)
{
// Base case: 0 operations are needed to reach 0
if (n == 0)
return 0;
// Operation 1: reach n from n - 1
int add = minOperation(n - 1);
// Operation 2: reach n from n / 2
int dbl = Integer.MAX_VALUE;
if (n % 2 == 0)
dbl = minOperation(n / 2);
// Take the minimum of both choices
return 1 + Math.min(add, dbl);
}
public static void main(String[] args)
{
int n = 7;
System.out.println(minOperation(n));
}
}
def minOperation(n):
# Base case: 0 operations are needed to reach 0
if n == 0:
return 0
# Operation 1: reach n from n - 1
add = minOperation(n - 1)
# Operation 2: reach n from n / 2
dbl = float('inf')
if n % 2 == 0:
dbl = minOperation(n // 2)
# Take the minimum of both choices
return 1 + min(add, dbl)
if __name__ == '__main__':
n = 7
print(minOperation(n))
using System;
public class GFG {
static int minOperation(int n)
{
// Base case: 0 operations are needed to reach 0
if (n == 0)
return 0;
// Operation 1: reach n from n - 1
int add = minOperation(n - 1);
// Operation 2: reach n from n / 2
int dbl = int.MaxValue;
if (n % 2 == 0)
dbl = minOperation(n / 2);
// Take the minimum of both choices
return 1 + Math.Min(add, dbl);
}
public static void Main()
{
int n = 7;
Console.WriteLine(minOperation(n));
}
}
function minOperation(n)
{
// Base case: 0 operations are needed to reach 0
if (n === 0)
return 0;
// Operation 1: reach n from n - 1
let add = minOperation(n - 1);
// Operation 2: reach n from n / 2
let dbl = Number.MAX_VALUE;
if (n % 2 === 0)
dbl = minOperation(Math.floor(n / 2));
// Take the minimum of both choices
return 1 + Math.min(add, dbl);
}
// Driver Code
let n = 7;
console.log(minOperation(n));
Output
5
[Better Approach] Using Dynamic Programming (Bottom-Up) - O(n) Time and O(n) Space
The idea is to use dynamic programming to store the minimum number of operations required to reach every number from 0 to n. For each number i, we can reach it by adding 1 to i - 1. If i is even, we can also reach it by doubling i / 2. We take the minimum of these two choices.
Working of Approach:
- Create a dp[] array where dp[i] stores the minimum operations needed to reach i.
- Initialize dp[0] = 0 since we start from 0.
- For every i, first consider reaching it using i - 1 + 1.
- If i is even, also consider reaching it by doubling i / 2.
- Store the minimum of both choices in dp[i] and return dp[n].
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int minOperation(int n)
{
vector<int> dp(n + 1, 0);
// dp[i] stores minimum operations to reach i
for (int i = 1; i <= n; i++)
{
// Reach i by adding 1 to i - 1
dp[i] = dp[i - 1] + 1;
// If i is even, reach i by doubling i / 2
if (i % 2 == 0)
dp[i] = min(dp[i], dp[i / 2] + 1);
}
return dp[n];
}
int main()
{
int n = 7;
cout << minOperation(n);
return 0;
}
import java.util.Arrays;
public class GFG {
public static int minOperation(int n)
{
int[] dp = new int[n + 1];
Arrays.fill(dp, 0);
// dp[i] stores minimum operations to reach i
for (int i = 1; i <= n; i++) {
// Reach i by adding 1 to i - 1
dp[i] = dp[i - 1] + 1;
// If i is even, reach i by doubling i / 2
if (i % 2 == 0)
dp[i] = Math.min(dp[i], dp[i / 2] + 1);
}
return dp[n];
}
public static void main(String[] args)
{
int n = 7;
System.out.println(minOperation(n));
}
}
def minOperation(n):
dp = [0] * (n + 1)
# dp[i] stores minimum operations to reach i
for i in range(1, n + 1):
# Reach i by adding 1 to i - 1
dp[i] = dp[i - 1] + 1
# If i is even, reach i by doubling i / 2
if i % 2 == 0:
dp[i] = min(dp[i], dp[i // 2] + 1)
return dp[n]
if __name__ == '__main__':
n = 7
print(minOperation(n))
using System;
public class GFG {
public static int minOperation(int n)
{
int[] dp = new int[n + 1];
// dp[i] stores minimum operations to reach i
for (int i = 1; i <= n; i++) {
// Reach i by adding 1 to i - 1
dp[i] = dp[i - 1] + 1;
// If i is even, reach i by doubling i / 2
if (i % 2 == 0)
dp[i] = Math.Min(dp[i], dp[i / 2] + 1);
}
return dp[n];
}
public static void Main()
{
int n = 7;
Console.WriteLine(minOperation(n));
}
}
function minOperation(n)
{
let dp = new Array(n + 1).fill(0);
// dp[i] stores minimum operations to reach i
for (let i = 1; i <= n; i++) {
// Reach i by adding 1 to i - 1
dp[i] = dp[i - 1] + 1;
// If i is even, reach i by doubling i / 2
if (i % 2 === 0)
dp[i] = Math.min(dp[i],
dp[Math.floor(i / 2)] + 1);
}
return dp[n];
}
// Driver Code
let n = 7;
console.log(minOperation(n));
Output
5
[Expected Approach] Using Greedy Reverse - O(log n) Time and O(1) Space
The idea is to work backwards from n to 0. When n is even, dividing it by 2 is optimal because it reverses the doubling operation. When n is odd, subtracting 1 is the only possible reverse operation.
Working of Approach:
- Start with n and work towards 0.
- If n is even, divide it by 2 to reverse the doubling operation.
- If n is odd, subtract 1 to reverse the +1 operation.
- Count each reverse operation.
- When n becomes 0, return the count.
Let us understand with an example:
Input: n = 7
- Initially, n = 7, which is odd, so perform n--. Now n = 6, cnt = 1.
- n = 6 is even, so divide it by 2. Now n = 3, cnt = 2.
- n = 3 is odd, so perform n--. Now n = 2, cnt = 3.
- n = 2 is even, so divide it by 2. Now n = 1, cnt = 4.
- n = 1 is odd, so perform n--. Now n = 0, cnt = 5.
Output: 5
#include <iostream>
using namespace std;
int minOperation(int n)
{
int cnt = 0;
while (n != 0)
{
// if n is even then it will be good to
// reach n from n/2 by multiplying it by 2.
if (n % 2 == 0)
n /= 2;
// if n is odd then we can reach n from n-- only.
else
n--;
cnt++;
}
return cnt;
}
int main()
{
int n = 7;
cout << minOperation(n);
return 0;
}
public class GFG {
int minOperation(int n)
{
int cnt = 0;
while (n != 0) {
// if n is even then it will be good to
// reach n from n/2 by multiplying it by 2.
if (n % 2 == 0)
n /= 2;
// if n is odd then we can reach n from n--
// only.
else
n--;
cnt++;
}
return cnt;
}
public static void main(String[] args)
{
GFG obj = new GFG();
int n = 7;
System.out.println(obj.minOperation(n));
}
}
def minOperation(n):
cnt = 0
while n != 0:
# if n is even then it will be good to
# reach n from n/2 by multiplying it by 2.
if n % 2 == 0:
n //= 2
# if n is odd then we can reach n from n-- only.
else:
n -= 1
cnt += 1
return cnt
if __name__ == '__main__':
n = 7
print(minOperation(n))
using System;
public class GFG {
public int minOperation(int n)
{
int cnt = 0;
while (n != 0) {
// if n is even then it will be good to
// reach n from n/2 by multiplying it by 2.
if (n % 2 == 0)
n /= 2;
// if n is odd then we can reach n from n--
// only.
else
n--;
cnt++;
}
return cnt;
}
public static void Main()
{
GFG obj = new GFG();
int n = 7;
Console.WriteLine(obj.minOperation(n));
}
}
function minOperation(n)
{
let cnt = 0;
while (n != 0) {
// if n is even then it will be good to
// reach n from n/2 by multiplying it by 2.
if (n % 2 == 0)
n = Math.floor(n / 2);
// if n is odd then we can reach n from n-- only.
else
n--;
cnt++;
}
return cnt;
}
// Driver Code
let n = 7;
console.log(minOperation(n));
Output
5