Count minimum steps to get the given desired array

Last Updated : 15 Jul, 2026

Given an array arr[]. Initially, you have another array containing only 0s. In one operation, you may either:

  • Choose any one element and increase its value by 1, or
  • Double the values of all elements in the array simultaneously.

Find the minimum number of operations required to transform the initial all-zero array into the given array arr[].

Examples: 

Input: arr[] = [16, 16, 16]
Output: 7
Explanation: First, increase each element to make the array [1, 1, 1] (3 steps).
Then, multiply the whole array by 2 four times:
[1,1,1] -> [2,2,2] -> [4,4,4] -> [8,8,8] -> [16,16,16]
Total steps = 3 + 4 = 7.

Input: arr[] = [2, 3]
Output: 4
Explanation: Start from [0, 0].
Increase both elements to get [1, 1] (2 steps)
Multiply once: [2, 2] (1 step)
Increase second element once: [2, 3] (1 step)
Total steps = 2 + 1 + 1 = 4.

Try It Yourself
redirect icon

[Naive Approach] BFS State Exploration - O(States × n) Time and O(States × n) Space

Start from all zeros array. Use BFS to explore all reachable states by applying two operations: increment one element or double all elements. First time target array is reached gives minimum operations.

C++
#include <iostream>
#include <vector>
#include <queue>
#include <set>
using namespace std;

int countMinOperations(vector<int>& arr) {
    int n = arr.size();
    vector<int> start(n, 0);

    queue<pair<vector<int>, int>> q;
    set<vector<int>> visited;

    q.push({start, 0});
    visited.insert(start);

    while (!q.empty()) {
        auto [curr, ops] = q.front();
        q.pop();

        if (curr == arr) {
            return ops;
        }

        // Try incrementing each individual element by 1
        for (int i = 0; i < n; i++) {
            vector<int> next = curr;
            next[i]++;

            bool valid = true;
            for (int j = 0; j < n; j++) {
                if (next[j] > arr[j]) {
                    valid = false;
                    break;
                }
            }

            if (valid && !visited.count(next)) {
                visited.insert(next);
                q.push({next, ops + 1});
            }
        }

        // Try doubling all elements in the array simultaneously
        vector<int> dbl = curr;
        for (int& x : dbl) {
            x *= 2;
        }

        bool valid = true;
        for (int i = 0; i < n; i++) {
            if (dbl[i] > arr[i]) {
                valid = false;
                break;
            }
        }

        if (valid && !visited.count(dbl)) {
            visited.insert(dbl);
            q.push({dbl, ops + 1});
        }
    }

    return -1;
}

int main() {
    vector<int> arr = {2, 3};

    cout << countMinOperations(arr) << endl;

    return 0;
}
Java
import java.util.Queue;
import java.util.Set;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.Arrays;

public class GFG {
    
    // Helper class to store the array state 
    // and the operations count together
    static class State {
        int[] arr;
        int ops;

        State(int[] arr, int ops) {
            this.arr = arr;
            this.ops = ops;
        }
    }

    public static int countMinOperations(int[] arr) {
        int n = arr.length;
        int[] start = new int[n];

        Queue<State> q = new LinkedList<>();
        
        // Track visited states cleanly as 
        // unique Strings instead of ArrayLists
        Set<String> visited = new HashSet<>();

        q.add(new State(start, 0));
        visited.add(Arrays.toString(start));

        while (!q.isEmpty()) {
            State currState = q.poll();
            int[] curr = currState.arr;
            int ops = currState.ops;

            if (Arrays.equals(curr, arr)) {
                return ops;
            }

            // Try incrementing each individual element by 1
            for (int i = 0; i < n; i++) {
                int[] next = curr.clone();
                next[i]++;

                boolean valid = true;
                for (int j = 0; j < n; j++) {
                    if (next[j] > arr[j]) {
                        valid = false;
                        break;
                    }
                }

                String nextStr = Arrays.toString(next);
                if (valid && !visited.contains(nextStr)) {
                    visited.add(nextStr);
                    q.add(new State(next, ops + 1));
                }
            }

            // Try doubling all elements in the array simultaneously
            int[] dbl = curr.clone();
            for (int i = 0; i < n; i++) {
                dbl[i] *= 2;
            }

            boolean valid = true;
            for (int i = 0; i < n; i++) {
                if (dbl[i] > arr[i]) {
                    valid = false;
                    break;
                }
            }

            String dblStr = Arrays.toString(dbl);
            if (valid && !visited.contains(dblStr)) {
                visited.add(dblStr);
                q.add(new State(dbl, ops + 1));
            }
        }

        return -1;
    }

    public static void main(String[] args) {
        int[] arr = {2, 3};

        System.out.println(countMinOperations(arr));
    }
}
Python
from collections import deque

# Helper class to store the array state and the operations count together
class State:
    def __init__(self, arr, ops):
        self.arr = arr
        self.ops = ops

# Helper method to convert primitive int[] array to list
def to_list(arr):
    return arr.copy()

def countMinOperations(arr):
    n = len(arr)
    start = [0] * n

    q = deque()
    visited = set()

    q.append(State(start, 0))
    visited.add(tuple(to_list(start)))

    while q:
        currState = q.popleft()
        curr = currState.arr
        ops = currState.ops

        if curr == arr:
            return ops

        # Try incrementing each individual element by 1
        for i in range(n):
            next = curr.copy()
            next[i] += 1

            valid = True
            for j in range(n):
                if next[j] > arr[j]:
                    valid = False
                    break

            if valid and tuple(next) not in visited:
                visited.add(tuple(next))
                q.append(State(next, ops + 1))

        # Try doubling all elements in the array simultaneously
        dbl = [x * 2 for x in curr]

        valid = True
        for i in range(n):
            if dbl[i] > arr[i]:
                valid = False
                break

        if valid and tuple(dbl) not in visited:
            visited.add(tuple(dbl))
            q.append(State(dbl, ops + 1))

    return -1

if __name__ == "__main__":
    arr = [2, 3]

    print(countMinOperations(arr))
C#
using System;
using System.Collections.Generic;

public class GFG {

    // Helper class to store the array state 
    // and the operations count together
    public class State {
        public int[] arr;
        public int ops;

        public State(int[] arr, int ops) {
            this.arr = arr;
            this.ops = ops;
        }
    }

    public static int countMinOperations(int[] arr) {
        int n = arr.Length;
        int[] start = new int[n];

        Queue<State> q = new Queue<State>();

        // Track visited states cleanly as 
        // unique Strings instead of ArrayLists
        HashSet<string> visited = new HashSet<string>();

        q.Enqueue(new State(start, 0));
        visited.Add(string.Join(", ", start));

        while (q.Count > 0) {
            State currState = q.Dequeue();
            int[] curr = currState.arr;
            int ops = currState.ops;

            if (arraysEqual(curr, arr)) {
                return ops;
            }

            // Try incrementing each individual element by 1
            for (int i = 0; i < n; i++) {
                int[] next = (int[])curr.Clone();
                next[i]++;

                bool valid = true;
                for (int j = 0; j < n; j++) {
                    if (next[j] > arr[j]) {
                        valid = false;
                        break;
                    }
                }

                string nextStr = string.Join(", ", next);
                if (valid &&!visited.Contains(nextStr)) {
                    visited.Add(nextStr);
                    q.Enqueue(new State(next, ops + 1));
                }
            }

            // Try doubling all elements in the array simultaneously
            int[] dbl = (int[])curr.Clone();
            for (int i = 0; i < n; i++) {
                dbl[i] *= 2;
            }

            bool valid2 = true;
            for (int i = 0; i < n; i++) {
                if (dbl[i] > arr[i]) {
                    valid2 = false;
                    break;
                }
            }

            string dblStr = string.Join(", ", dbl);
            if (valid2 &&!visited.Contains(dblStr)) {
                visited.Add(dblStr);
                q.Enqueue(new State(dbl, ops + 1));
            }
        }

        return -1;
    }

    private static bool arraysEqual(int[] a, int[] b) {
        if (ReferenceEquals(a, b))
            return true;

        if (a == null || b == null)
            return false;

        if (a.Length!= b.Length)
            return false;

        for (int i = 0; i < a.Length; i++) {
            if (a[i]!= b[i])
                return false;
        }

        return true;
    }

    public static void Main(string[] args) {
        int[] arr = {2, 3};

        Console.WriteLine(countMinOperations(arr));
    }
}
JavaScript
// Helper function to store the array state 
// and the operations count together
function createState(arr, ops) {
    return { arr, ops };
}

function countMinOperations(arr) {
    let n = arr.length;
    let start = new Array(n).fill(0);
    
    let q = [];
    let visited = new Set();

    q.push(createState(start, 0));
    visited.add(start.toString());

    while (q.length > 0) {
        let currState = q.shift();
        let curr = currState.arr;
        let ops = currState.ops;

        // Check if current array matches the target array
        if (JSON.stringify(curr) === JSON.stringify(arr)) {
            return ops;
        }

        // Try incrementing each individual element by 1
        for (let i = 0; i < n; i++) {
            let next = [...curr];
            next[i]++;

            let valid = true;
            for (let j = 0; j < n; j++) {
                if (next[j] > arr[j]) {
                    valid = false;
                    break;
                }
            }

            let nextStr = next.toString();
            if (valid && !visited.has(nextStr)) {
                visited.add(nextStr);
                q.push(createState(next, ops + 1));
            }
        }

        // Try doubling all elements in the array simultaneously
        let dbl = [...curr];
        for (let i = 0; i < n; i++) {
            dbl[i] *= 2;
        }

        let valid = true;
        for (let i = 0; i < n; i++) {
            if (dbl[i] > arr[i]) {
                valid = false;
                break;
            }
        }

        let dblStr = dbl.toString();
        if (valid && !visited.has(dblStr)) {
            visited.add(dblStr);
            q.push(createState(dbl, ops + 1));
        }
    }

    return -1;
}

// Driver code
let arr = [2, 3];
console.log(countMinOperations(arr));

Output
4

[Expected Approach] Reverse Greedy - O(n × log m) Time and O(n) Space

Work backwards from target array to all zeros. Odd numbers must have come from increment operation, so decrement them. When all numbers become even, undo one doubling by dividing all by 2.

  • Copy arr to nums array
  • Initialize operations = 0
  • While not all zeros
  • If any number is odd, decrement it and increment operations
  • If all numbers are even and at least one non-zero, divide all by 2 and increment operations
  • Return operations
C++
#include <iostream>
#include <vector>
using namespace std;

int countMinOperations(vector<int>& arr) {
    vector<int> nums = arr;
    int ops = 0;

    while (true) {
        bool allZero = true;
        for (int val : nums) {
            if (val != 0) {
                allZero = false;
                break;
            }
        }

        if (allZero) {
            return ops;
        }

        // Undo increment operations for any odd numbers
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] & 1) {
                nums[i]--;
                ops++;
            }
        }

        bool hasNonZero = false;
        for (int val : nums) {
            if (val > 0) {
                hasNonZero = true;
                break;
            }
        }

        // Undo one simultaneous doubling operation 
        // by dividing all elements by 2
        if (hasNonZero) {
            for (int& val : nums) {
                val /= 2;
            }
            ops++;
        }
    }
}

int main() {
    vector<int> arr = {2, 3};

    cout << countMinOperations(arr) << endl;

    return 0;
}
Java
class GFG {
    public static int countMinOperations(int[] arr) {
        int[] nums = arr.clone();
        int ops = 0;

        while (true) {
            boolean allZero = true;
            for (int val : nums) {
                if (val != 0) {
                    allZero = false;
                    break;
                }
            }

            if (allZero) {
                return ops;
            }

            // Undo increment operations for any odd numbers
            for (int i = 0; i < nums.length; i++) {
                if ((nums[i] & 1) != 0) {
                    nums[i]--;
                    ops++;
                }
            }

            boolean hasNonZero = false;
            for (int val : nums) {
                if (val > 0) {
                    hasNonZero = true;
                    break;
                }
            }

            // Undo one simultaneous doubling operation 
            // by dividing all elements by 2
            if (hasNonZero) {
                for (int i = 0; i < nums.length; i++) {
                    nums[i] /= 2;
                }
                ops++;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {2, 3};

        System.out.println(countMinOperations(arr));
    }
}
Python
def countMinOperations(arr):
    nums = arr.copy()
    ops = 0

    while True:
        all_zero = all(val == 0 for val in nums)

        if all_zero:
            return ops

        # Undo increment operations for any odd numbers
        for i in range(len(nums)):
            if nums[i] % 2!= 0:
                nums[i] -= 1
                ops += 1

        has_non_zero = any(val > 0 for val in nums)

        # Undo one simultaneous doubling operation 
        # by dividing all elements by 2
        if has_non_zero:
            for i in range(len(nums)):
                nums[i] //= 2
            ops += 1

if __name__ == '__main__':
    arr = [2, 3]

    print(countMinOperations(arr))
C#
using System;

class GFG {
    public static int countMinOperations(int[] arr) {
        int[] nums = (int[])arr.Clone();
        int ops = 0;

        while (true) {
            bool allZero = true;
            foreach (int val in nums) {
                if (val!= 0) {
                    allZero = false;
                    break;
                }
            }

            if (allZero) {
                return ops;
            }

            // Undo increment operations for any odd numbers
            for (int i = 0; i < nums.Length; i++) {
                if ((nums[i] & 1)!= 0) {
                    nums[i]--;
                    ops++;
                }
            }

            bool hasNonZero = false;
            foreach (int val in nums) {
                if (val > 0) {
                    hasNonZero = true;
                    break;
                }
            }

            // Undo one simultaneous doubling operation 
            // by dividing all elements by 2
            if (hasNonZero) {
                for (int i = 0; i < nums.Length; i++) {
                    nums[i] /= 2;
                }
                ops++;
            }
        }
    }

    public static void Main(string[] args) {
        int[] arr = {2, 3};

        Console.WriteLine(countMinOperations(arr));
    }
}
JavaScript
function countMinOperations(arr) {
    let nums = [...arr];
    let ops = 0;

    while (true) {
        let allZero = nums.every(val => val === 0);

        if (allZero) {
            return ops;
        }

        // Undo increment operations for any odd numbers
        for (let i = 0; i < nums.length; i++) {
            if (nums[i] % 2!== 0) {
                nums[i]--;
                ops++;
            }
        }

        let hasNonZero = nums.some(val => val > 0);

        // Undo one simultaneous doubling operation 
        // by dividing all elements by 2
        if (hasNonZero) {
            for (let i = 0; i < nums.length; i++) {
                nums[i] = Math.floor(nums[i] / 2);
            }
            ops++;
        }
    }
}

// Driver code
let arr = [2, 3];

console.log(countMinOperations(arr));

Output
4

[Optimal Approach] Bit Manipulation - O(n × log m) Time and O(1) Space

Each set bit in binary representation corresponds to an increment operation. Number of doubling operations equals maximum bit length minus one. Total operations = total set bits + (max bit length - 1).

Initialize incs = 0, maxLen = 0
For each val in array

  • Check if the lowest bit is set (val & 1) to count and add to incs
  • Compute bit length len by right shifting until val becomes 0
  • Update maxLen with maximum bit length found

Compute dbls = max(0, maxLen - 1)
Return incs + dbls

C++
#include <iostream>
#include <vector>
#include <algorithm> 
using namespace std;

int countMinOperations(vector<int>& arr) {
    
    // Tracks total increment operations (set bits)
    int incs = 0;  
    
    // Tracks the maximum bit length found
    int maxLen = 0;  

    for (int val : arr) {
        int len = 0;

        while (val > 0) {
            
            // An odd number (lowest bit set) implies an increment operation
            if (val & 1) {
                incs++;
            }
            len++;
            // Shift right to inspect the next bit
            val >>= 1; 
        }

        maxLen = max(maxLen, len);
    }

    // Total doubling operations equals (max bit length - 1)
    int dbls = max(0, maxLen - 1);

    return incs + dbls;
}

int main() {
    vector<int> arr = {2, 3};

    cout << countMinOperations(arr) << endl;

    return 0;
}
Java
import java.util.Arrays;

class GFG {
    public static int countMinOperations(int[] arr) {
        
        // Tracks total increment operations (set bits)
        int incs = 0;  
        
        // Tracks the maximum bit length found
        int maxLen = 0;  
        
        for (int val : arr) {
            int len = 0;

            while (val > 0) {
                
                // An odd number (lowest bit set) implies an increment operation
                if ((val & 1)!= 0) {
                    incs++;
                }
                len++;
                // Shift right to inspect the next bit
                val >>= 1; 
            }

            maxLen = Math.max(maxLen, len);
        }

        // Total doubling operations equals (max bit length - 1)
        int dbls = Math.max(0, maxLen - 1);

        return incs + dbls;
    }

    public static void main(String[] args) {
        int[] arr = {2, 3};

        System.out.println(countMinOperations(arr));
    }
}
Python
def countMinOperations(arr):
    
    # Tracks total increment operations (set bits)
    incs = 0  
    
    # Tracks the maximum bit length found
    maxLen = 0  
    
    for val in arr:
        len = 0
        
        while val > 0:
            
            # An odd number (lowest bit set) implies an increment operation
            if (val & 1)!= 0:
                incs += 1
            len += 1
            # Shift right to inspect the next bit
            val >>= 1 
        
        maxLen = max(maxLen, len)
    
    # Total doubling operations equals (max bit length - 1)
    dbls = max(0, maxLen - 1)
    
    return incs + dbls

if __name__ == "__main__":
    arr = [2, 3]
    
    print(countMinOperations(arr))
C#
using System;

class GFG {
    public static int countMinOperations(int[] arr) {
        
        // Tracks total increment operations (set bits)
        int incs = 0; 
        
        // Tracks the maximum bit length found
        int maxLen = 0; 

        foreach (int val in arr) {
            int len = 0;
            
            // Create a modifiable copy of the foreach variable
            int temp = val; 

            while (temp > 0) {
                
                // An odd number (lowest bit set) implies an increment operation
                if ((temp & 1) != 0) {
                    incs++;
                }
                len++;
                
                // Shift right to inspect the next bit
                temp >>= 1; 
            }
            maxLen = Math.Max(maxLen, len);
        }

        // Total doubling operations equals (max bit length - 1)
        int dbls = Math.Max(0, maxLen - 1); 
        return incs + dbls;
    }

    public static void Main(string[] args) {
        int[] arr = { 2, 3 };
        Console.WriteLine(countMinOperations(arr));
    }
}
JavaScript
function countMinOperations(arr)
{
    // Tracks total increment operations (set bits)
    let incs = 0;

    // Tracks the maximum bit length found
    let maxLen = 0;

    for (let val of arr) {
        let len = 0;

        while (val > 0) {

            // An odd number (lowest bit set) implies an
            // increment operation
            if ((val & 1) != 0) {
                incs++;
            }
            len++;
            
            // Shift right to inspect the next bit
            val >>= 1;
        }

        maxLen = Math.max(maxLen, len);
    }

    // Total doubling operations equals (max bit length - 1)
    let dbls = Math.max(0, maxLen - 1);

    return incs + dbls;
}

// Driver code
let arr = [2, 3];

console.log(countMinOperations(arr));

Output
4
Comment