Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
-
给你一个整数数组 ,请你找出 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。
-
如果数组 可以由数组 删除一些元素(或不删除)得到,则认为数组 是数组 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
-
对数组 执行 按位或 ,结果等于 (下标从 开始)。
-
1 <= nums.length <= 16 -
1 <= nums[i] <= 105 -
示例 1
输入: nums = [3,1]
输出: 2
解释: 子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 :
- [3]
- [3,1]
- 示例 2
输入: nums = [2,2,2]
输出: 7
解释: [2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。
- 示例 3
输入:nums = [3,2,1,5]
输出:6
解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :
- [3,5]
- [3,1,5]
- [3,2,5]
- [3,2,1,5]
- [2,5]
- [2,1,5]
思路分析
- 根据题目给出的数据范围,子集的最大数量可能为 其中 ,我们就可以直接用回溯方法了。
- 维护一个已经遍历过的子集或的最大值并进行计数,当出现比当前值更大时同时更新最大值记录和计数变量。详解见 ac 代码。
AC 代码
class Solution {
// 记录子集或的最大值.
int maxValue;
// 记录子集最大值数量.
int count;
int n;
public int countMaxOrSubsets(int[] nums) {
n = nums.length;
dfs(nums, 0, 0);
return count;
}
private void dfs(int[] nums, int index, int pre) {
if (index >= n) return;
for (int i = index; i < n; i++) {
int cur = pre | nums[i];
if (cur > maxValue) { // 当前子集或值大于最大值,更新 count、maxValue.
count = 1;
maxValue = cur;
} else if (cur == maxValue) { // 当前值等于最大值,更新 count.
count++;
}
dfs(nums, i + 1, cur);
}
}
}
总结
- 今天的 leetcode 每日一题比较常规,但是在回溯操作的时候要注意回溯判断条件,不然的话可能会出现超时的情况。