2044. Count Number of Maximum Bitwise-OR Subsets - Detailed Explanation
Problem Statement
Given an array of integers, a subset’s bitwise OR is defined as the OR of all its elements. Your task is to return the number of non‐empty subsets that have a bitwise OR equal to the maximum possible bitwise OR obtainable from any subset of the array.
Example 1
- Input:
nums = [3, 1]
- Output:
2
- Explanation:
The maximum possible bitwise OR is calculated as:
( 3 ;|; 1 = 3 )
The subsets and their OR values are:- ([3]) → 3
- ([1]) → 1
- ([3,1]) → (3 ;|; 1 = 3)
The subsets with OR equal to 3 are ([3]) and ([3,1]), so the answer is 2.
Example 2
- Input:
nums = [2, 2, 2]
- Output:
7
- Explanation:
The maximum bitwise OR is:
( 2 ;|; 2 ;|; 2 = 2 )
Every non-empty subset has an OR of 2. There are (2^3 - 1 = 7) non-empty subsets, so the answer is 7.
Constraints
- The array length is small enough (often ( n \leq 16 )) so that iterating over all (2^n) subsets is feasible.
- All numbers are non-negative integers.
Hints and Intuition
-
Maximum OR Insight:
The maximum bitwise OR possible is simply the OR of all elements in the array. Any subset cannot exceed this value. -
Subset Enumeration:
Since the maximum OR is known, your goal is to count the number of non-empty subsets whose OR equals this maximum. You can use either a recursive (backtracking) DFS or iterative bit masking to enumerate all subsets. -
Recursive DFS Approach:
Use a helper function that at each index decides whether to include the current number (thus updating the current OR) or to skip it. When you reach the end of the array, check if the computed OR equals the maximum. -
Iterative Approach:
Alternatively, iterate through all bit masks (from 1 to (2^n - 1)) to compute the OR for each non-empty subset and count those matching the maximum.
Detailed Approaches
Approach A: Recursive DFS (Backtracking)
-
Pre-computation:
Compute the maximum OR by OR-ing all numbers in the array. This value is the target for each subset. -
Recursive Function:
Define a recursive functiondfs(index, currentOR)
that:- Base Case: When the index reaches the end of the array, if
currentOR
equals the maximum OR, increment the count. - Decision: At each index, you have two choices:
- Skip the current number (do not update the OR).
- Include the current number (update the OR using the bitwise OR operator).
- Base Case: When the index reaches the end of the array, if
-
Return the Count:
After exploring all non-empty subsets, return the total count.
Approach B: Iterative Bit Masking
-
Pre-computation:
Again, compute the maximum OR of the entire array. -
Enumerate Subsets:
For each integermask
from 1 to (2^n - 1):- Compute the OR of the subset represented by the mask.
- If the computed OR equals the maximum, increment the count.
Step-by-Step Walkthrough (Using Recursive DFS)
Let’s walk through the example nums = [3, 1]
:
-
Calculate Maximum OR:
( maxOR = 3 ;|; 1 = 3 ) -
Start DFS:
Calldfs(0, 0)
whereindex = 0
andcurrentOR = 0
. -
At Index 0:
- Skip Option: Call
dfs(1, 0)
. - Include Option: Update
currentOR
to (0 ;|; 3 = 3) and calldfs(1, 3)
.
- Skip Option: Call
-
At Index 1:
For the calldfs(1, 0)
:- Skip Option: Call
dfs(2, 0)
→ at the end, OR is 0 (does not equal maximum). - Include Option: Call
dfs(2, 0 \;|\; 1 = 1)
→ at the end, OR is 1.
For the call
dfs(1, 3)
:- Skip Option: Call
dfs(2, 3)
→ at the end, OR is 3 (equals maximum; count 1). - Include Option: Call
dfs(2, 3 \;|\; 1 = 3)
→ at the end, OR is 3 (equals maximum; count another).
- Skip Option: Call
-
Final Count:
The recursive DFS finds 2 subsets with OR equal to 3: ([3]) and ([3,1]).
Code Implementation
Python Implementation (Recursive DFS)
Java Implementation (Recursive DFS)
Complexity Analysis
-
Time Complexity:
The recursive DFS explores each of the (2^n) possible subsets. Hence, the time complexity is O(2^n), where (n) is the number of elements in the array. -
Space Complexity:
The space complexity is O(n) due to the recursion stack depth (in the worst-case, when the recursion goes as deep as the number of elements).
Common Pitfalls and Edge Cases
Common Pitfalls:
-
Counting the Empty Subset:
Make sure not to count the empty subset (unless the problem explicitly includes it). In our DFS, the base case checks after the entire array is processed. -
Incorrect OR Calculation:
Ensure that the bitwise OR is updated correctly when including an element. -
Recursion Limit:
Although the constraints are small, be cautious with recursion in languages with limited recursion depth.
Edge Cases:
-
Single Element Array:
For example, if (nums = [a]), the maximum OR is (a) and the only non-empty subset is ([a]), so the answer should be 1. -
Arrays Where All Elements Are the Same:
If (nums = [2, 2, 2]), every non-empty subset’s OR will equal 2. The answer should be (2^n - 1).
Related Problems for Further Practice
-
Subset Sum Problems:
Problems that require enumerating subsets to meet a certain condition. -
Bitwise Manipulation Challenges:
Other problems that involve using bitwise operations to solve puzzles or optimization problems. -
Count Subsets:
Problems where you count the number of subsets that satisfy specific conditions.
GET YOUR FREE
Coding Questions Catalog