Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 60e1a33

Browse files
✨feat: Add 2044
1 parent 3487b45 commit 60e1a33

File tree

5 files changed

+185
-0
lines changed

5 files changed

+185
-0
lines changed

‎Index/DFS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@
3232
| [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/) | 中等 | 🤩🤩🤩🤩🤩 |
3333
| [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/) | 困难 | 🤩🤩🤩 |
3434
| [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/) | 困难 | 🤩🤩🤩🤩 |
35+
| [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/) | 困难 | 🤩🤩🤩🤩 |
3536

‎Index/二进制枚举.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- |
33
| [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/) | 中等 | 🤩🤩🤩 |
44
| [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/) | 中等 | 🤩🤩🤩🤩 |
5+
| [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/) | 困难 | 🤩🤩🤩🤩 |
56

‎Index/位运算.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
| [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/) | 中等 | 🤩🤩🤩 |
1818
| [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/) | 困难 | 🤩🤩🤩🤩 |
1919
| [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/) | 中等 | 🤩🤩🤩 |
20+
| [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/) | 困难 | 🤩🤩🤩🤩 |
2021
| [剑指 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/) | 简单 | 🤩🤩🤩 |
2122

‎Index/状压 DP.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
| [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/) | 中等 | 🤩🤩🤩🤩🤩 |
44
| [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/) | 困难 | 🤩🤩🤩🤩🤩 |
55
| [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/) | 困难 | 🤩🤩🤩🤩 |
6+
| [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/) | 困难 | 🤩🤩🤩🤩 |
67

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/)** ,难度为 **中等**
4+
5+
Tag : 「二进制枚举」、「位运算」、「DFS」、「状压 DP」
6+
7+
8+
9+
给你一个整数数组 $nums$ ,请你找出 $nums$ 子集 **按位或** 可能得到的 **最大值** ,并返回按位或能得到最大值的 **不同非空子集的数目**
10+
11+
如果数组 $a$ 可以由数组 $b$ 删除一些元素(或不删除)得到,则认为数组 $a$ 是数组 $b$ 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
12+
13+
对数组 $a$ 执行 **按位或** ,结果等于 $a[0]$ `OR` $a[1]$ `OR` `...` `OR` $a[a.length - 1]$(下标从 0ドル$ 开始)。
14+
15+
示例 1:
16+
```
17+
输入:nums = [3,1]
18+
19+
输出:2
20+
21+
解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 :
22+
- [3]
23+
- [3,1]
24+
```
25+
示例 2:
26+
```
27+
输入:nums = [2,2,2]
28+
29+
输出:7
30+
31+
解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。
32+
```
33+
示例 3:
34+
```
35+
输入:nums = [3,2,1,5]
36+
37+
输出:6
38+
39+
解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :
40+
- [3,5]
41+
- [3,1,5]
42+
- [3,2,5]
43+
- [3,2,1,5]
44+
- [2,5]
45+
- [2,1,5]
46+
```
47+
48+
提示:
49+
* 1ドル <= nums.length <= 16$
50+
* 1ドル <= nums[i] <= 10^5$
51+
52+
---
53+
54+
### 二进制枚举
55+
56+
令 $n$ 为 $nums$ 的长度,利用 $n$ 不超过 16ドル,ドル我们可以使用一个 `int` 数值来代指 $nums$ 的使用情况(子集状态)。
57+
58+
假设当前子集状态为 $state,ドル$state$ 为一个仅考虑低 $n$ 位的二进制数,当第 $k$ 位为 1ドル,ドル代表 $nums[k]$ 参与到当前的按位或运算,当第 $k$ 位为 0ドル,ドル代表 $nums[i]$ 不参与到当前的按位或运算。
59+
60+
在枚举这 2ドル^n$ 个状态过程中,我们使用变量 `max` 记录最大的按位或得分,使用 `ans` 记录能够取得最大得分的状态数量。
61+
62+
代码:
63+
```Java
64+
class Solution {
65+
public int countMaxOrSubsets(int[] nums) {
66+
int n = nums.length, mask = 1 << n;
67+
int max = 0, ans = 0;
68+
for (int s = 0; s < mask; s++) {
69+
int cur = 0;
70+
for (int i = 0; i < n; i++) {
71+
if (((s >> i) & 1) == 1) cur |= nums[i];
72+
}
73+
if (cur > max) {
74+
max = cur; ans = 1;
75+
} else if (cur == max) {
76+
ans++;
77+
}
78+
}
79+
return ans;
80+
}
81+
}
82+
```
83+
* 时间复杂度:令 $nums$ 长度为 $n,ドル共有 2ドル^n$ 个子集状态,计算每个状态的按位或得分的复杂度为 $O(n)$。整体复杂度为 $O(2^n * n)$
84+
* 空间复杂度:$O(1)$
85+
86+
87+
---
88+
89+
### 状压 DP
90+
91+
为了优化解法一中「每次都要计算某个子集的得分」这一操作,我们可以将所有状态的得分记下来,采用「动态规划」思想进行优化。
92+
93+
需要找到当前状态 $state$ 可由哪些状态转移而来:假设当前 $state$ 中处于最低位的 1ドル$ 位于第 $idx$ 位,首先我们可以使用 `lowbit` 操作得到「仅保留第 $idx$ 的 1ドル$ 所对应的数值」,记为 $lowbit,ドル那么显然对应的状态方程为:
94+
95+
$$
96+
f[state] = f[state - lowbit] \wedge nums[idx]
97+
$$
98+
99+
再配合我们从小到大枚举所有的 $state$ 即可确保计算 $f[state]$ 时所依赖的 $f[state - lowbit]$ 已被计算。
100+
101+
最后为了快速知道数值 $lowbit$ 最低位 1ドル$ 所处于第几位(也就是 $idx$ 为何值),我们可以利用 $nums$ 长度最多不超过 16ドル$ 来进行「打表」预处理。
102+
103+
代码:
104+
```Java
105+
class Solution {
106+
static Map<Integer, Integer> map = new HashMap<>();
107+
static {
108+
for (int i = 0; i < 20; i++) map.put((1 << i), i);
109+
}
110+
public int countMaxOrSubsets(int[] nums) {
111+
int n = nums.length, mask = 1 << n;
112+
int[] f = new int[mask];
113+
int max = 0, ans = 0;
114+
for (int s = 1; s < mask; s++) {
115+
int lowbit = (s & -s);
116+
int prev = s - lowbit, idx = map.get(lowbit);
117+
f[s] = f[prev] | nums[idx];
118+
if (f[s] > max) {
119+
max = f[s]; ans = 1;
120+
} else if (f[s] == max) {
121+
ans++;
122+
}
123+
}
124+
return ans;
125+
}
126+
}
127+
```
128+
* 时间复杂度:$O(2^n)$
129+
* 空间复杂度:$O(2^n)$
130+
131+
---
132+
133+
### DFS
134+
135+
解法一将「枚举子集/状态」&「计算状态对应的得分」两个过程分开进行,导致了复杂度上界为 $O(2^n * n)$。
136+
137+
事实上,我们可以在「枚举子集」的同时「计算相应得分」,设计 `void dfs(int u, int val)``DFS` 函数来实现「爆搜」,其中 $u$ 为当前的搜索到 $nums$ 的第几位,$val$ 为当前的得分情况。
138+
139+
对于任意一位 $x$ 而言,都有「选」和「不选」两种选择,分别对应了 `dfs(u + 1, val | nums[x])``dfs(u + 1, val)` 两条搜索路径,在搜索所有状态过程中,使用全局变量 `max``ans` 来记录「最大得分」以及「取得最大得分的状态数量」。
140+
141+
该做法将多条「具有相同前缀」的搜索路径的公共计算部分进行了复用,从而将算法复杂度下降为 $O(2^n)$。
142+
143+
代码:
144+
```Java
145+
class Solution {
146+
int[] nums;
147+
int max = 0, ans = 0;
148+
public int countMaxOrSubsets(int[] _nums) {
149+
nums = _nums;
150+
dfs(0, 0);
151+
return ans;
152+
}
153+
void dfs(int u, int val) {
154+
if (u == nums.length) {
155+
if (val > max) {
156+
max = val; ans = 1;
157+
} else if (val == max) {
158+
ans++;
159+
}
160+
return ;
161+
}
162+
dfs(u + 1, val);
163+
dfs(u + 1, val | nums[u]);
164+
}
165+
}
166+
```
167+
* 时间复杂度:令 $nums$ 长度为 $n,ドル共有 2ドル^n$ 个子集状态。整体复杂度为 $O(2^n)$
168+
* 空间复杂度:忽略递归带来的额外空间开销,复杂度为 $O(1)$
169+
170+
---
171+
172+
### 最后
173+
174+
这是我们「刷穿 LeetCode」系列文章的第 `No.2044` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
175+
176+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
177+
178+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
179+
180+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
181+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /