统计按位或能得到最大值的子集数目-LeetCode
2044. 统计按位或能得到最大值的子集数目
🎯 问题描述(来源于LeetCode)
描述:
给你一个整数数组 nums,找出所有可能的子集(包括空集)的按位或(OR)运算结果。
返回能够获得最大按位或值的子集个数。
注意:子集可以是空集,空集按位或为 0。
说明:
- 子集定义为原数组中任意元素组成的集合(顺序无关)。
- 不同子集如果元素相同但顺序不同视为同一个子集。
示例:
- 示例 1:
1 | 输入: nums = [3,1] |
- 示例 2:
1 | 输入: nums = [2,2,2] |
💻 解题思路
思路:回溯法(DFS)枚举所有子集
算法步骤
- 获取数组长度
n,初始化max_num = -1(确保任何非负的 OR 值都会大于它),cnt = 0。 - 定义递归函数
dfs(i, path),其中i表示当前处理的下标,path为当前子集的按位或值:- 如果
i == n,说明子集构造完成:- 若
path > max_num,则更新max_num = path,并重置cnt = 1。 - 否则若
path == max_num,则cnt += 1。 - 返回。
- 若
- 否则,进行两个分支:
- 不选
nums[i]:dfs(i+1, path) - 选
nums[i]:dfs(i+1, path | nums[i])
- 不选
- 如果
- 从
dfs(0, 0)开始搜索。 - 返回最终的
cnt。
代码实现
1 | from typing import List |
📊 性能分析
- 时间复杂度:,每个子集枚举一次。
- 空间复杂度:,递归栈深度。
思考
该回溯解法与上一版相比,将 max_num 初始值从 1 改进为 -1,避免了当所有数均为 0 时(尽管题目数据可能不会出现)无法正确更新最大值的隐患,更具鲁棒性。代码仍然简洁高效,通过 path > max_num 和 path == max_num 分别处理新最大值和相等值的计数。
此方法适合 n ≤ 16 的小规模数据。若数据规模增大,可预先计算全局最大 OR 值(即所有元素的按位或),然后使用 DP 或 Meet-in-the-Middle 统计子集 OR 值等于该最大值的个数,但回溯法已足够通过本题的测试范围。
注意:递归中两个 dfs 的顺序(先不选后选)不影响结果,但保证了空集(path=0)被正确计入。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






