We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Minimum Operations to Form Subsequence With Target Sum

Number: 3025

Difficulty: Hard

Paid? No

Companies: Media.net, Amazon


Problem Description

Given an array nums consisting of non-negative powers of 2 and an integer target, the goal is to determine the minimum number of operations required so that nums contains a subsequence whose elements sum exactly to target. In one operation, you select any element nums[i] such that nums[i] > 1, remove it, and append two copies of nums[i] / 2 to the end of nums. If it is impossible to obtain such a subsequence, return -1.


Key Insights

  • Count the frequency of each power-of-two present in the array.
  • Use a greedy approach that tries to “pay” for each bit in target starting from the least significant bit.
  • If current resources (frequency at the current bit) are insufficient to cover a needed bit in the target, look for a higher power and split it down until you can cover the deficiency.
  • After processing a lower bit, combine leftover elements (every pair of 2^i makes one 2^(i+1)) to use them in upcoming higher bits.
  • Checking the total sum first avoids unnecessary computation if the target is unachievable.

Space and Time Complexity

Time Complexity: O(61^2) ≈ O(1) because we only iterate over a fixed number (up to 61) of bit-level positions. Space Complexity: O(61) ≈ O(1) for the frequency array.


Solution

We first count the occurrence of each power-of-two from the nums array into a frequency array indexed by the exponent. Also, we verify that the total sum of the nums is at least target; if not, return -1.

The algorithm iterates from the least significant bit (bit 0) up to an upper bound (e.g. bit 60 when considering target < 2^31 and potential splits). For each bit:

  1. Carry any extra numbers from lower bits upward (since two copies of 2^i form one 2^(i+1)).
  2. If the required bit (i.e., if target has a 1 in the i-th position) is missing and there is no available element at that bit, search for the next higher bit that has an available element.
  3. Once found, perform splitting operations: decrease the count in the higher bit by one and increase the count in the next lower bit by two, incrementing the operation counter on each split, until you reach the desired bit level.
  4. Finally, "spend" one unit at the current bit to cover the target's requirement.

This greedy splitting ensures the minimal number of operations. The use of a frequency array and the careful combining of lower bits into higher ones allow us to solve the problem efficiently.


Code Solutions

Below are implementations in Python, JavaScript, C++, and Java with line-by-line comments.

# Python Implementation
import math

def minOperations(nums, target):
    # Maximum possible exponent; 61 is sufficient for our constraints.
    MAX_BIT = 61
    # Frequency array to count occurrences of powers of two.
    freq = [0] * MAX_BIT

    # Build frequency array: count how many numbers are 2^i.
    for num in nums:
        exp = int(math.log2(num))
        freq[exp] += 1

    # Check if the total sum of nums is at least target.
    total = sum(num for num in nums)
    if total < target:
        return -1

    operations = 0

    # Loop through each bit position.
    for i in range(MAX_BIT):
        # Add extra from lower bits: two numbers of 2^i form one 2^(i+1).
        if i > 0:
            freq[i] += freq[i-1] // 2

        # Check if the ith bit of target is set.
        if (target >> i) & 1:
            # If no 2^i is available, we need to split a larger number.
            if freq[i] <= 0:
                j = i + 1
                # Find a higher bit where an element is available.
                while j < MAX_BIT and freq[j] <= 0:
                    j += 1
                if j == MAX_BIT:
                    return -1  # Not possible to cover target.

                # Split the number at bit position j until you reach i.
                while j > i:
                    # One operation: split one 2^j into two 2^(j-1).
                    freq[j] -= 1
                    freq[j-1] += 2
                    operations += 1
                    j -= 1

            # Use one 2^i number to cover the bit.
            freq[i] -= 1

    return operations

# Example usage:
print(minOperations([1, 2, 8], 7))  # Expected output: 1
← Back to All Questions