Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Index/DFS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@
| [1609. 奇偶树](https://leetcode-cn.com/problems/even-odd-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/even-odd-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-bfs-d-kuyi/) | 中等 | 🤩🤩🤩🤩🤩 |
| [1723. 完成所有工作的最短时间](https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/solution/gong-shui-san-xie-yi-ti-shuang-jie-jian-4epdd/) | 困难 | 🤩🤩🤩 |
| [1766. 互质树](https://leetcode-cn.com/problems/tree-of-coprimes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/tree-of-coprimes/solution/bu-tai-yi-yang-de-dfs-ji-lu-suo-you-zui-d3xeu/) | 困难 | 🤩🤩🤩🤩 |
| [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/) | 困难 | 🤩🤩🤩🤩 |

1 change: 1 addition & 0 deletions Index/二进制枚举.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- |
| [1239. 串联字符串的最大长度](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/solution/gong-shui-san-xie-yi-ti-san-jie-jian-zhi-nfeb/) | 中等 | 🤩🤩🤩 |
| [1601. 最多可达成的换楼请求数目](https://leetcode-cn.com/problems/maximum-number-of-achievable-transfer-requests/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-number-of-achievable-transfer-requests/solution/gong-shui-san-xie-er-jin-zhi-mei-ju-by-a-enef/) | 中等 | 🤩🤩🤩🤩 |
| [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/) | 困难 | 🤩🤩🤩🤩 |

1 change: 1 addition & 0 deletions Index/位运算.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
| [526. 优美的排列](https://leetcode-cn.com/problems/beautiful-arrangement/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/beautiful-arrangement/solution/gong-shui-san-xie-xiang-jie-liang-chong-vgsia/) | 中等 | 🤩🤩🤩 |
| [1178. 猜字谜](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/solution/xiang-jin-zhu-shi-xiang-jie-po-su-wei-yu-3cr2/) | 困难 | 🤩🤩🤩🤩 |
| [1711. 大餐计数](https://leetcode-cn.com/problems/count-good-meals/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-good-meals/solution/gong-shui-san-xie-xiang-jie-san-chong-gu-nn4f/) | 中等 | 🤩🤩🤩 |
| [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/) | 困难 | 🤩🤩🤩🤩 |
| [剑指 Offer 15. 二进制中1的个数](https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-wei-shu-j-g9w6/) | 简单 | 🤩🤩🤩 |

1 change: 1 addition & 0 deletions Index/状压 DP.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
| [526. 优美的排列](https://leetcode-cn.com/problems/beautiful-arrangement/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/beautiful-arrangement/solution/gong-shui-san-xie-xiang-jie-liang-chong-vgsia/) | 中等 | 🤩🤩🤩🤩🤩 |
| [847. 访问所有节点的最短路径](https://leetcode-cn.com/problems/shortest-path-visiting-all-nodes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/shortest-path-visiting-all-nodes/solution/gong-shui-san-xie-yi-ti-shuang-jie-bfs-z-6p2k/) | 困难 | 🤩🤩🤩🤩🤩 |
| [1994. 好子集的数目](https://leetcode-cn.com/problems/the-number-of-good-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/the-number-of-good-subsets/solution/gong-shui-san-xie-zhuang-ya-dp-yun-yong-gz4w5/) | 困难 | 🤩🤩🤩🤩 |
| [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/) | 困难 | 🤩🤩🤩🤩 |

Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
### 题目描述

这是 LeetCode 上的 **[2044. 统计按位或能得到最大值的子集数目]()** ,难度为 **中等**。
这是 LeetCode 上的 **[2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/)** ,难度为 **中等**。

Tag : 「二进制枚举」、「位运算」、「回溯算法
Tag : 「二进制枚举」、「位运算」、「DFS」、「状压 DP



给你一个整数数组 $nums$ ,请你找出 $nums$ 子集 **按位或** 可能得到的 最大值 ,并返回按位或能得到最大值的 **不同非空子集的数目** 。
给你一个整数数组 $nums$ ,请你找出 $nums$ 子集 **按位或** 可能得到的 **最大值** ,并返回按位或能得到最大值的 **不同非空子集的数目** 。

如果数组 $a$ 可以由数组 $b$ 删除一些元素(或不删除)得到,则认为数组 $a$ 是数组 $b$ 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。

对数组 $a$ 执行 按位或 ,结果等于 $a[0]$ `OR` $a[1]$ `OR` `...` `OR` $a[a.length - 1]$(下标从 $0$ 开始)。
对数组 $a$ 执行 **按位或** ,结果等于 $a[0]$ `OR` $a[1]$ `OR` `...` `OR` $a[a.length - 1]$(下标从 $0$ 开始)。

示例 1:
```
Expand Down Expand Up @@ -60,7 +60,7 @@ Tag : 「二进制枚举」、「位运算」、「回溯算法」
在枚举这 $2^n$ 个状态过程中,我们使用变量 `max` 记录最大的按位或得分,使用 `ans` 记录能够取得最大得分的状态数量。

代码:
```Java
```Java
class Solution {
public int countMaxOrSubsets(int[] nums) {
int n = nums.length, mask = 1 << n;
Expand All @@ -80,17 +80,68 @@ class Solution {
}
}
```
* 时间复杂度:令 $nums$ 长度为 $n$,共有 $2^n$ 个子集状态,计算每个状态的按位或答案复杂度为 $O(n)。$整体复杂度为 $O(2^n * n)$
* 时间复杂度:令 $nums$ 长度为 $n$,共有 $2^n$ 个子集状态,计算每个状态的按位或得分的复杂度为 $O(n)$。整体复杂度为 $O(2^n * n)$
* 空间复杂度:$O(1)$


---

### 回溯算法
### 状压 DP

为了优化解法一中「每次都要计算某个子集的得分」这一操作,我们可以将所有状态的得分记下来,采用「动态规划」思想进行优化。

需要找到当前状态 $state$ 可由哪些状态转移而来:假设当前 $state$ 中处于最低位的 $1$ 位于第 $idx$ 位,首先我们可以使用 `lowbit` 操作得到「仅保留第 $idx$ 的 $1$ 所对应的数值」,记为 $lowbit$,那么显然对应的状态方程为:

$$
f[state] = f[state - lowbit] \wedge nums[idx]
$$

再配合我们从小到大枚举所有的 $state$ 即可确保计算 $f[state]$ 时所依赖的 $f[state - lowbit]$ 已被计算。

最后为了快速知道数值 $lowbit$ 最低位 $1$ 所处于第几位(也就是 $idx$ 为何值),我们可以利用 $nums$ 长度最多不超过 $16$ 来进行「打表」预处理。

代码:
```Java
class Solution {
static Map<Integer, Integer> map = new HashMap<>();
static {
for (int i = 0; i < 20; i++) map.put((1 << i), i);
}
public int countMaxOrSubsets(int[] nums) {
int n = nums.length, mask = 1 << n;
int[] f = new int[mask];
int max = 0, ans = 0;
for (int s = 1; s < mask; s++) {
int lowbit = (s & -s);
int prev = s - lowbit, idx = map.get(lowbit);
f[s] = f[prev] | nums[idx];
if (f[s] > max) {
max = f[s]; ans = 1;
} else if (f[s] == max) {
ans++;
}
}
return ans;
}
}
```
* 时间复杂度:$O(2^n)$
* 空间复杂度:$O(2^n)$

---

### DFS

解法一将「枚举子集/状态」&「计算状态对应的得分」两个过程分开进行,导致了复杂度上界为 $O(2^n * n)$。

事实上,我们可以在「枚举子集」的同时「计算相应得分」,设计 `void dfs(int u, int val)` 的 `DFS` 函数来实现「爆搜」,其中 $u$ 为当前的搜索到 $nums$ 的第几位,$val$ 为当前的得分情况。

对于任意一位 $x$ 而言,都有「选」和「不选」两种选择,分别对应了 `dfs(u + 1, val | nums[x])` 和 `dfs(u + 1, val)` 两条搜索路径,在搜索所有状态过程中,使用全局变量 `max` 和 `ans` 来记录「最大得分」以及「取得最大得分的状态数量」。

该做法将多条「具有相同前缀」的搜索路径的公共计算部分进行了复用,从而将算法复杂度下降为 $O(2^n)$。

代码:
```Java
```Java
class Solution {
int[] nums;
int max = 0, ans = 0;
Expand All @@ -113,7 +164,7 @@ class Solution {
}
}
```
* 时间复杂度:令 $nums$ 长度为 $n$,共有 $2^n$ 个子集状态。$整体复杂度为 $O(2^n * n)$
* 时间复杂度:令 $nums$ 长度为 $n$,共有 $2^n$ 个子集状态。整体复杂度为 $O(2^n)$
* 空间复杂度:忽略递归带来的额外空间开销,复杂度为 $O(1)$

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class Solution {
}
}
```
* 时间复杂度:$O(n)$
* 时间复杂度:$O(n + m)$
* 空间复杂度:$O(n)$

---
Expand Down