{x}
blog image

Minimum Numbers of Function Calls to Make Target Array

You are given an integer array nums. You have an integer array arr of the same length with all values set to 0 initially. You also have the following modify function:

You want to use the modify function to convert arr to nums using the minimum number of calls.

Return the minimum number of function calls to make nums from arr.

The test cases are generated so that the answer fits in a 32-bit signed integer.

 

Example 1:

Input: nums = [1,5]
Output: 5
Explanation: Increment by 1 (second element): [0, 0] to get [0, 1] (1 operation).
Double all the elements: [0, 1] -> [0, 2] -> [0, 4] (2 operations).
Increment by 1 (both elements)  [0, 4] -> [1, 4] -> [1, 5] (2 operations).
Total of operations: 1 + 2 + 2 = 5.

Example 2:

Input: nums = [2,2]
Output: 3
Explanation: Increment by 1 (both elements) [0, 0] -> [0, 1] -> [1, 1] (2 operations).
Double all the elements: [1, 1] -> [2, 2] (1 operation).
Total of operations: 2 + 1 = 3.

Example 3:

Input: nums = [4,2,5]
Output: 6
Explanation: (initial)[0,0,0] -> [1,0,0] -> [1,0,1] -> [2,0,2] -> [2,1,2] -> [4,2,4] -> [4,2,5](nums).

 

Constraints:

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 109

Solution Explanation

This problem asks for the minimum number of operations to transform an array of zeros into a target array nums using two operations:

  1. Increment: Add 1 to each element in the array.
  2. Double: Double each element in the array.

The solution uses a greedy approach combined with bit manipulation for efficiency. The key insight is that we can analyze the binary representation of each number in nums.

Algorithm:

  1. Count Set Bits: For each number n in nums, count the number of set bits (1s) in its binary representation. This represents the number of increment operations needed to reach that number if we start from 0, assuming we can double at any time. Sum these counts.

  2. Find Maximum and its Leading Zeros: Find the maximum number mx in nums. The number of leading zeros in mx's binary representation (excluding the leading 1) indicates how many doubling operations are needed to reach a number greater than or equal to mx. This is because each doubling operation shifts the bits to the left by 1.

  3. Total Operations: The total minimum operations are the sum of the set bits (from step 1) plus the number of doubling operations (from step 2).

Time Complexity Analysis:

  • The loop iterating through nums takes O(N) time, where N is the length of nums.
  • Counting set bits (using Integer.bitCount() or similar functions) for each number takes O(log M) time in the worst case for a number M, but it is typically very fast, practically considered constant time in most cases.
  • Finding the maximum number takes O(N) time.
  • Determining the number of doubling operations takes O(log M) time, which is again effectively constant time for practical purposes.

Therefore, the overall time complexity is O(N), dominated by the iteration through the input array.

Space Complexity Analysis:

The solution uses only a few variables to store intermediate results. The space complexity is O(1), which is constant.

Code Explanation (Python):

class Solution:
    def minOperations(self, nums: List[int]) -> int:
        return sum(v.bit_count() for v in nums) + max(0, max(nums).bit_length() - 1)

This concise Python code leverages the built-in bit_count() method (available in Python 3.10+) to efficiently count set bits. bit_length() gives the number of bits needed to represent a number. The max(0, ...) handles the case where nums contains only zeros.

Code Explanation (Java):

class Solution {
    public int minOperations(int[] nums) {
        int ans = 0;
        int mx = 0;
        for (int v : nums) {
            mx = Math.max(mx, v);
            ans += Integer.bitCount(v); // Counts set bits
        }
        //  Integer.toBinaryString(mx).length() -1 is equivalent to the calculation  31 - Integer.numberOfLeadingZeros(mx) but more concise.
        ans += Integer.toBinaryString(mx).length() - 1; 
        return ans;
    }
}

The Java code uses Integer.bitCount() for set bit counting and a similar approach to determine the number of doubling operations.

The C++ and Go code follow a similar approach but use their respective bit manipulation functions. The Go code is slightly less concise as it explicitly implements the set bit count instead of using a built-in function.