class Solution:
def minOperations(self, nums):
add_ops = 0
max_doubles = 0
for num in nums:
curr_doubles = 0
n = num
while n > 0:
if n % 2 == 1:
add_ops += 1
n //= 2
if n > 0:
curr_doubles += 1
max_doubles = max(max_doubles, curr_doubles)
return add_ops + max_doubles
class Solution {
public:
int minOperations(vector<int>& nums) {
int add_ops = 0, max_doubles = 0;
for (int num : nums) {
int curr_doubles = 0;
int n = num;
while (n > 0) {
if (n % 2 == 1)
add_ops++;
n /= 2;
if (n > 0)
curr_doubles++;
}
max_doubles = max(max_doubles, curr_doubles);
}
return add_ops + max_doubles;
}
};
class Solution {
public int minOperations(int[] nums) {
int addOps = 0, maxDoubles = 0;
for (int num : nums) {
int currDoubles = 0;
int n = num;
while (n > 0) {
if (n % 2 == 1)
addOps++;
n /= 2;
if (n > 0)
currDoubles++;
}
maxDoubles = Math.max(maxDoubles, currDoubles);
}
return addOps + maxDoubles;
}
}
var minOperations = function(nums) {
let addOps = 0, maxDoubles = 0;
for (let num of nums) {
let currDoubles = 0;
let n = num;
while (n > 0) {
if (n % 2 === 1)
addOps++;
n = Math.floor(n / 2);
if (n > 0)
currDoubles++;
}
maxDoubles = Math.max(maxDoubles, currDoubles);
}
return addOps + maxDoubles;
};
Given a target array nums
of positive integers, you start with an array of zeros of the same length. You can perform two types of operations any number of times:
Your goal is to find the minimum number of function calls (operations) needed to transform the initial zero array into nums
. Each operation applies to the whole array (for double) or a single index (for increment). You may not reuse elements; each operation must be a valid step toward the target.
At first glance, it might seem like you need to simulate the process forward: starting from zeros, incrementing elements and doubling the array until you reach the target. However, this quickly becomes inefficient, especially for large numbers.
Instead, let's think in reverse: What if we started from the target array and tried to reduce it to zeros, counting the operations needed? Every time we see an odd number, we know an increment must have occurred. Every time all numbers are even, we know a double operation was used. This reverse approach lets us efficiently count operations without simulating every step.
By analyzing the binary representation of each number, we can see that each '1' bit corresponds to an increment, and the highest bit position corresponds to the number of doubles needed.
nums
, count how many times you need to increment (i.e., how many '1's are in its binary representation).
This approach is efficient and avoids simulating every possible operation. It leverages the properties of binary numbers and the allowed operations.
Let's walk through the problem with the sample input nums = [2, 3]
:
The sequence of operations could be:
[0, 0] → increment index 0 → [1, 0]
[1, 0] → increment index 1 → [1, 1]
[1, 1] → double all → [2, 2]
[2, 2] → increment index 1 → [2, 3]
nums
and M is the maximum value in nums
.
The key insight in this problem is to reverse the process and analyze the binary representation of each number. Each increment corresponds to a '1' bit, and the highest bit position gives the number of double operations needed. By summing all increments and taking the maximum doubles, we efficiently compute the minimum number of function calls. This approach is both elegant and efficient, leveraging fundamental properties of binary numbers and the allowed operations.