↓Skip to main content
  1. LeetCode/

LeetCode 4040: Minimum Operations to Form Subset Sum I

·2 mins· ·
LeetCode Medium Dynamic-Programming Knapsack Array
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2026-08-30

  • Submissions: Accepted ×2

Approach
#

Multiplying x by 2 a times and then halving b times:

  • a >= b: the result is x × 2^(a - b), reachable with only a - b multiplications, in fewer steps.
  • a < b: the result is x // 2^(b - a), reachable with only b - a divisions, in fewer steps.

So each number has just two kinds of options:

  • x, 2x, 4x, ... (up to sum), costing 0, 1, 2, ....
  • x // 2, x // 4, ... (above 0), costing 1, 2, ....

Then it is a grouped 0/1 knapsack: each number picks one option or none, with dp[s] = the fewest operations for a subset summing to exactly s.

My Solution
#

class Solution:
    def minOperations(self, nums: List[int], sum: int) -> int:
        INF = float("inf")
        dp = [0] + [INF] * sum                     # dp[s]: fewest operations for subset sum s
        for x in nums:
            options = []
            v, cost = x, 0
            while v <= sum:                        # multiply only
                options.append((v, cost))
                v, cost = v * 2, cost + 1
            v, cost = x // 2, 1
            while v > 0:                           # divide only
                if v <= sum:
                    options.append((v, cost))
                v, cost = v // 2, cost + 1

            for s in range(sum, -1, -1):           # backwards: each number used at most once
                if dp[s] == INF:
                    continue
                for v, cost in options:
                    if s + v <= sum:
                        dp[s + v] = min(dp[s + v], dp[s] + cost)
        return dp[sum] if dp[sum] < INF else -1

This pushes from dp[s] into dp[s + v]; with s running backwards, dp[s] always still holds the previous number’s value.

Complexity
#

Time O(n · sum · log(sum)), space O(sum).

Mistakes to Avoid
#

  • Enumerating every mix of multiplications and divisions: no multiply-then-divide mix beats pure multiplying or pure dividing.
  • Values divided down to 0 are useless; leave them out of the options.

Interview Explanation
#

With multiplications before divisions they cancel, so the best is always multiply-only or divide-only. I list each number’s reachable values with their costs; each number picks at most one, giving a grouped 0/1 knapsack where dp[s] is the fewest operations for subset sum s, with capacity running backwards. Time O(n · sum · log(sum)).

Related

LeetCode 4041: Minimum Operations to Form Subset Sum II
·2 mins
LeetCode Hard Dynamic-Programming Knapsack Breadth-First-Search Array
LeetCode 4041 note: with operations in any order, BFS finds every value a number can become (up to sum) with the fewest steps, then the same grouped 0/1 knapsack as 4040
LeetCode 2585: Number of Ways to Earn Points
·2 mins
LeetCode Hard Dynamic-Programming Knapsack Array
LeetCode 2585 note: a bounded (grouped) knapsack; each question type takes 0 to count questions, with capacity running backwards and the count enumerated inside
LeetCode 3660: Jump Game IX
·2 mins
LeetCode Medium Dynamic-Programming Array
LeetCode 3660 note: cutting between i and i+1, if the left max exceeds the right min the two sides reach each other and share the answer; otherwise the left answer is the left max
LeetCode 3840: House Robber V
·2 mins
LeetCode Medium Dynamic-Programming Array
LeetCode 3840 note: houses conflict only when adjacent with the same color; take a house outright when the colors differ, and do the House Robber choice only when they match
LeetCode 1493: Longest Subarray of 1's After Deleting One Element
·2 mins
LeetCode Medium Sliding-Window Dynamic-Programming Array
LeetCode 1493 note: find the longest window with at most one 0; since one element must be deleted, the answer is the window length minus 1
LeetCode 3638: Maximum Balanced Shipments
·2 mins
LeetCode Medium Dynamic-Programming Greedy Monotonic-Stack Array
LeetCode 3638 note: greedily cut a segment as soon as a value below its maximum appears; until then the segment is non-decreasing, so its maximum is the previous value