githubEdit

28. Count Subset With Target Sum II

βœ… GFG solution to Count Subset With Target Sum II: find the number of subsets with sum equal to k using meet-in-the-middle technique for optimal performance. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

You are given an array arr[] and an integer k. Your task is to find the count of subsets whose sum equals k.

A subset is any combination of elements from the array (including the empty subset). The goal is to efficiently count all possible subsets that sum to the target value k.

Note: It is guaranteed that the number of valid subsets will fit within a 32-bit integer.

πŸ“˜ Examples

Example 1

Input: arr[] = [1, 3, 2], k = 3
Output: 2
Explanation: The two subsets whose sum equals k are [1, 2] and [3].

Example 2

Input: arr[] = [4, 2, 3, 1, 2], k = 4
Output: 3
Explanation: The three subsets whose sum equals k are [4], [2, 2] and [3, 1].

Example 3

πŸ”’ Constraints

  • $1 \le \text{arr.size()} \le 40$

  • $-10^7 \le \text{arr}[i], k \le 10^7$

βœ… My Approach

The optimal solution uses the Meet-in-the-Middle technique, which is perfect for subset problems with constraints up to n ≀ 40:

Meet-in-the-Middle with Hash Map

  1. Split Array:

    • Divide the array into two halves of approximately equal size.

    • This reduces the problem space from O(2^n) to O(2^(n/2)).

  2. Generate Subset Sums:

    • For the left half, recursively generate all possible subset sums and store their frequencies in a hash map.

    • For the right half, do the same and store in another hash map.

  3. Combine Results:

    • For each sum s in the left half, check if k - s exists in the right half.

    • If it exists, multiply their frequencies to get the count of valid pairs.

    • Accumulate all such counts to get the final answer.

  4. Recursive Generation:

    • Use a recursive lambda function to explore both choices: include or exclude current element.

    • Base case: when we've processed all elements, increment frequency of current sum.

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(2^(n/2) Γ— n), where n is the size of the array. We generate all 2^(n/2) subsets for each half, and for each subset, we perform O(n) operations in the worst case to calculate the sum. The final combination step takes O(2^(n/2)) to iterate through one map and perform constant-time lookups in the other.

  • Expected Auxiliary Space Complexity: O(2^(n/2)), as we store all possible subset sums for both halves in hash maps. In the worst case, each half can have up to 2^(n/2) unique subset sums, and we also use O(n) recursion stack space.

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ Iterative Bitmask Approach

πŸ’‘ Algorithm Steps:

  1. Split array into two halves for divide and conquer optimization.

  2. Use bitmask iteration to generate all possible subset sums for each half.

  3. Store frequency of each subset sum in hash maps.

  4. For each sum in left half, find complement in right half and multiply frequencies.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(2^(n/2) Γ— n) - Generate subsets for both halves with bit operations

  • Auxiliary Space: πŸ’Ύ O(2^(n/2)) - Store subset sums in hash maps

βœ… Why This Approach?

  • Avoids recursion overhead with iterative generation

  • Clear bit manipulation for subset enumeration

  • Better for understanding meet-in-the-middle technique

πŸ“Š 3️⃣ Dynamic Programming Approach

πŸ’‘ Algorithm Steps:

  1. Use DP to count subsets with specific sums in each half.

  2. Create frequency maps for achievable sums in left and right halves.

  3. Build DP table iteratively for each element.

  4. Combine results by matching complementary sums.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(2^(n/2) Γ— log(2^(n/2))) - Map operations for each subset

  • Auxiliary Space: πŸ’Ύ O(2^(n/2)) - DP state storage

βœ… Why This Approach?

  • Builds solution incrementally element by element

  • More intuitive for DP-familiar programmers

  • Easier to extend for weighted variants

πŸ“Š 4️⃣ Optimized Vector-Based Storage

πŸ’‘ Algorithm Steps:

  1. Generate all subset sums using vectors instead of hash maps.

  2. Sort one vector for binary search optimization.

  3. For each sum in first vector, binary search for complement.

  4. Count matching pairs efficiently.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(2^(n/2) Γ— (n + log(2^(n/2)))) - Sorting and binary search

  • Auxiliary Space: πŸ’Ύ O(2^(n/2)) - Vector storage

βœ… Why This Approach?

  • Cache-friendly vector access patterns

  • Binary search for efficient counting

  • Good for competitive programming constraints

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

πŸ”„ Recursive Lambda

🟒 O(2^(n/2) Γ— n)

🟒 O(2^(n/2))

πŸš€ Clean and concise

πŸ”§ Recursion stack overhead

🎯 Iterative Bitmask

🟒 O(2^(n/2) Γ— n)

🟒 O(2^(n/2))

πŸ“– No recursion overhead

πŸ”’ Bit manipulation complexity

πŸ“Š Dynamic Programming

🟑 O(2^(n/2) Γ— log n)

🟒 O(2^(n/2))

🎯 Incremental building

🐌 Map overhead

πŸ” Vector Binary Search

🟑 O(2^(n/2) Γ— log n)

🟒 O(2^(n/2))

⚑ Cache-friendly

πŸ”§ Sorting required

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… Optimal performance needed

πŸ₯‡ Recursive Lambda

β˜…β˜…β˜…β˜…β˜…

πŸ“– Avoid recursion

πŸ₯ˆ Iterative Bitmask

β˜…β˜…β˜…β˜…β˜†

πŸ”§ DP understanding

πŸ₯‰ Dynamic Programming

β˜…β˜…β˜…β˜…β˜†

🎯 Cache optimization

πŸ… Vector Binary Search

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated