💡 Multiple subsets can share the maximum OR value.
reconstruct
Return final count
All subsets processed; return count which is 2, the number of subsets with max OR.
💡 The final count is the answer to the problem.
Line:return count
💡 The algorithm correctly counted subsets with maximum bitwise OR.
from typing import List
class Solution:
def countMaxOrSubsets(self, nums: List[int]) -> int:
n = len(nums) # STEP 1
max_or = 0 # STEP 1
count = 0 # STEP 1
for mask in range(1, 1 << n): # STEP 2,6,10
current_or = 0 # STEP 2,6,10
for i in range(n): # STEP 3,4,7,8,11,12
if mask & (1 << i): # STEP 3,4,7,8,11,12
current_or |= nums[i] # STEP 3,8,11,12
if current_or > max_or: # STEP 5,13
max_or = current_or # STEP 5
count = 1 # STEP 5
elif current_or == max_or: # STEP 13
count += 1 # STEP 13
return count # STEP 14
if __name__ == '__main__':
sol = Solution()
print(sol.countMaxOrSubsets([3,1])) # Expected output: 2
print(sol.countMaxOrSubsets([2,2,2])) # Expected output: 7
📊
Count Number of Max Bitwise-OR Subsets - Watch the Algorithm Execute, Step by Step
Watching each subset being generated and evaluated helps you understand how bitmask enumeration works and why the algorithm correctly counts subsets with the maximum bitwise OR.
Step 1/14
·Active fill★Answer cell
enteringnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Remaining
mask=1 to 3
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1
Remaining
mask=2mask=3
Partial: [mask=1]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1, i=0 included
Remaining
mask=1, i=1 excluded
Partial: [mask=1, included nums[0]=3]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1, i=0 includedmask=1, i=1 excluded
Partial: [mask=1, included nums[0]=3]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1 processed
Remaining
mask=2mask=3
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1mask=2
Remaining
mask=3
Partial: [mask=2]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=2, i=0 excluded
Remaining
mask=2, i=1 included
Partial: [mask=2]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=2, i=0 excludedmask=2, i=1 included
Partial: [mask=2, included nums[1]=1]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1mask=2
Remaining
mask=3
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1mask=2mask=3
Partial: [mask=3]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=3, i=0 included
Remaining
mask=3, i=1 included
Partial: [mask=3, included nums[0]=3]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=3, i=0 includedmask=3, i=1 included
Partial: [mask=3, included nums[0]=3, included nums[1]=1]
choosingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1mask=2mask=3
backtrackingnums=[3,1]
Call Path (current → root)
countMaxOrSubsets([3,1])
Tried
mask=1mask=2mask=3
Found 1: [2]
Key Takeaways
✓ Enumerating subsets with bitmasks allows systematic and complete exploration of all subsets.
This is hard to see from code alone because the bitmask iteration looks like a loop, but visualizing each mask as a subset clarifies the process.
✓ The bitwise OR operation accumulates values from included elements, revealing how subsets combine bits.
Seeing the OR build step-by-step helps understand why the OR of a subset is computed by OR-ing included elements.
✓ Tracking max_or and count separately shows how the algorithm updates the best OR and counts subsets achieving it.
The decision to reset count or increment it is clearer when watching each subset's OR compared to max_or.
Practice
(1/5)
1. Consider the following Python function that counts subsets with sum K using a space-optimized DP approach. What is the output when called with arr = [1, 2, 3, 3] and K = 6?
def count_subsets_space_optimized(arr, K):
dp = [0] * (K + 1)
dp[0] = 1
for num in arr:
for j in range(K, num - 1, -1):
dp[j] += dp[j - num]
return dp[K]
print(count_subsets_space_optimized(arr, K))
easy
A. 5
B. 4
C. 3
D. 6
Solution
Step 1: Initialize dp array
dp = [1,0,0,0,0,0,0] since dp[0]=1 and K=6.
Step 2: Process each number updating dp
After processing 1: dp = [1,1,0,0,0,0,0]
After 2: dp = [1,1,1,1,0,0,0]
After first 3: dp = [1,1,1,2,1,1,1]
After second 3: dp = [1,1,1,3,2,2,3]
Final Answer:
Option A -> Option A
Quick Check:
dp[6] = 5 subsets sum to 6 [OK]
Hint: Trace dp updates backward to avoid double counting [OK]
Common Mistakes:
Forgetting to iterate backward in dp array
Off-by-one errors in dp indices
2. The following code attempts to count subsets with sum K using space-optimized DP. Identify the line that contains a subtle bug that can cause incorrect results.
def count_subsets_space_optimized(arr, K):
dp = [0] * (K + 1)
dp[0] = 1
for num in arr:
for j in range(num, K + 1):
dp[j] += dp[j - num]
return dp[K]
medium
A. for j in range(num, K + 1):
B. dp[0] = 1
C. dp = [0] * (K + 1)
D. dp[j] += dp[j - num]
Solution
Step 1: Analyze iteration order
The inner loop iterates forward from num to K, which causes dp[j] to use updated dp values from the same iteration, leading to overcounting.
Step 2: Correct iteration direction
To avoid overcounting, the inner loop must iterate backward from K down to num.
Final Answer:
Option A -> Option A
Quick Check:
Forward iteration in DP causes incorrect counts -> bug in loop range [OK]
Hint: Inner loop must iterate backward to avoid reuse of updated dp values [OK]
Common Mistakes:
Using forward iteration in space-optimized DP
Misunderstanding dp update dependencies
3. The following backtracking code attempts to generate all subsets of nums. What is the subtle bug causing incorrect output?
medium
A. Using global variable without resetting between calls
B. Not copying the current subset before appending to result causes all subsets to be the same list
C. Base case missing the empty subset
D. Forgetting to pop after including an element causes subsets to accumulate extra elements
Solution
Step 1: Analyze base case append
The code appends path directly without copying, so all appended references point to the same mutable list.
Step 2: Consequence of mutation
As recursion unwinds and path changes, all entries in result reflect the final state of path, causing incorrect subsets.
Final Answer:
Option B -> Option B
Quick Check:
Appending a copy (path[:]) fixes the bug [OK]
Hint: Always append a copy of the current path to result [OK]
Common Mistakes:
Forgetting to pop after append
Misunderstanding base case inclusion
4. Suppose you want to generate all combinations of size k from numbers 1 to n, but now elements can be reused multiple times in a combination (combinations with replacement). Which modification to the backtracking approach correctly handles this?
hard
A. Use iterative lexicographic generation without any changes
B. Change the recursive call to backtrack(i + 1, path) to prevent reuse of elements
C. Change the recursive call to backtrack(i, path) to allow reuse of the current element
D. Sort the input array before backtracking to handle duplicates
Solution
Step 1: Understand combinations with replacement allow repeated elements
To allow reuse, the recursive call must not increment start index beyond current element.
Step 2: Modify recursion to backtrack(i, path) to allow current element reuse
This ensures the same element can be chosen multiple times in subsequent recursive calls.
Final Answer:
Option C -> Option C
Quick Check:
Using backtrack(i, path) enables combinations with replacement [OK]
Hint: Reuse requires recursive calls with same start index [OK]
Common Mistakes:
Incrementing start index prevents element reuse
5. Suppose the problem is modified so that each element in the array can be used multiple times to form the k equal sum subsets (i.e., unlimited reuse of elements). Which modification to the backtracking with bitmask memoization approach is necessary to correctly solve this variant?
hard
A. Keep bitmask but allow resetting bits after each recursive call
B. Sort ascending instead of descending to handle reuse properly
C. Use the same code without changes because bitmask handles reuse implicitly
D. Remove bitmask usage since elements can be reused; track counts instead
Solution
Step 1: Understand reuse impact on state representation
Bitmask tracks used elements uniquely; with reuse allowed, usage state is not binary but counts.
Step 2: Modify approach accordingly
Bitmask must be removed or replaced by frequency counts to track how many times each element is used; otherwise, states are incorrect.
Final Answer:
Option D -> Option D
Quick Check:
Bitmask cannot represent multiple uses of same element [OK]
Hint: Bitmask tracks usage once; reuse breaks this assumption [OK]