2044. Count Number of Maximum Bitwise-OR Subsets

Created: 10/28/2021

Leetcode

Given an integer array nums, find the maximum possible bitwise OR of a subset of nums and return the number of different non-empty subsets with the maximum bitwise OR.

An array a is a subset of an array b if a can be obtained from b by deleting some (possibly zero) elements of b. Two subsets are considered different if the indices of the elements chosen are different.

The bitwise OR of an array a is equal to a[0] OR a[1] OR ... OR a[a.length - 1] (0-indexed).

Example 1:

Input: nums = [3,1]
Output: 2
Explanation: The maximum possible bitwise OR of a subset is 3. There are 2 subsets with a bitwise OR of 3:
- [3]
- [3,1]

Example 2:

Input: nums = [2,2,2]
Output: 7
Explanation: All non-empty subsets of [2,2,2] have a bitwise OR of 2. There are 23 - 1 = 7 total subsets.

Example 3:

Input: nums = [3,2,1,5]
Output: 6
Explanation: The maximum possible bitwise OR of a subset is 7. There are 6 subsets with a bitwise OR of 7:
- [3,5]
- [3,1,5]
- [3,2,5]
- [3,2,1,5]
- [2,5]
- [2,1,5]

Constraints:

  • 1 <= nums.length <= 16

  • 1 <= nums[i] <= 10^5

Basic Idea:

有两个思路,首先因为一共只有16个数字,所以即使暴力枚举所有的subsets也只需要O(2^16=65536)的时间复杂度,所以暴力解是行得通的。二则是可以使用DP的思路,利用如下递推公式。时间复杂度为O(len(nums) * bitwise or 结果的数字范围),当nums比较多的时候,复杂度会远优于brute force。

int[][] dp = new int[nums.length + 1][1<<17]
dp[0][0] = 1
for i from 0 to nums.length
    for j from 0 to 1<<17
        if (dp[i][j] > 0){
            dp[i + 1][j] += dp[i][j]
            dp[i + 1][nums[i] | j] += dp[i][j]
        }
    }
}

# dp[i][j] 表示到第i个数字为止,能够通过or产生的j的组合个数

Java Code:

// DP 
class Solution {
    public int countMaxOrSubsets(int[] nums) {
        int N = 1<<17;
        int[] dp = new int[N];
        dp[0] = 1;
        for (int num : nums) {
            int[] dp2 = new int[N];
            for (int i = 0; i < dp.length; ++i) {
                if (dp[i] > 0) {
                    dp2[i | num] += dp[i];
                    dp2[i] += dp[i];
                }
            }
            dp = dp2;
        }
        int max = 0;
        int count = 0;
        for (int i = 0; i < N; ++i) {
            if (dp[i] > 0) {
                count = dp[i];
            }
        }
        return count;
    }
}

// Brute force
class Solution {
    public int countMaxOrSubsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        dfs(nums, 0, new ArrayList<>(), res);
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for (List<Integer> list : res) {
            int curr = 0;
            for (int num : list) {
                curr |= num;
            }
            map.put(curr, map.getOrDefault(curr, 0) + 1);
        }
        return map.lastEntry().getValue();
    }
    
    private void dfs(int[] nums, int pos, List<Integer> path, List<List<Integer>> res) {
        res.add(new ArrayList<>(path));
        if (pos == nums.length) {
            return;
        }
        for (int i = pos; i < nums.length; ++i) {
            path.add(nums[i]);
            dfs(nums, i + 1, path, res);
            path.remove(path.size() - 1);
        }
    }
}

Last updated