Skip to content

Commit 6057bf3

Browse files
author
oushihao
committed
feat(count-number-of-maximum-bitwise-or-subsets): 回溯 | 位运算
1 parent 92d04dc commit 6057bf3

File tree

7 files changed

+238
-0
lines changed

7 files changed

+238
-0
lines changed

assets/data/category.json

+17
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,12 @@
12931293
"title": "最多可达成的换楼请求数目",
12941294
"path": "../../problemset/maximum-number-of-achievable-transfer-requests/README.md",
12951295
"difficulty": "困难"
1296+
},
1297+
{
1298+
"id": 2044,
1299+
"title": "统计按位或能得到最大值的子集数目",
1300+
"path": "../../problemset/count-number-of-maximum-bitwise-or-subsets/README.md",
1301+
"difficulty": "中等"
12961302
}
12971303
]
12981304
},
@@ -1845,5 +1851,16 @@
18451851
"difficulty": "困难"
18461852
}
18471853
]
1854+
},
1855+
{
1856+
"label": "位运算",
1857+
"problems": [
1858+
{
1859+
"id": 2044,
1860+
"title": "统计按位或能得到最大值的子集数目",
1861+
"path": "../../problemset/count-number-of-maximum-bitwise-or-subsets/README.md",
1862+
"difficulty": "中等"
1863+
}
1864+
]
18481865
}
18491866
]

assets/data/problems.json

+10
Original file line numberDiff line numberDiff line change
@@ -2059,6 +2059,16 @@
20592059
"url": "https://leetcode-cn.com/problems/maximum-difference-between-increasing-elements/",
20602060
"path": "../../problemset/maximum-difference-between-increasing-elements/README.md"
20612061
},
2062+
{
2063+
"id": 2044,
2064+
"title": {
2065+
"cn": "统计按位或能得到最大值的子集数目",
2066+
"en": "count-number-of-maximum-bitwise-or-subsets"
2067+
},
2068+
"difficulty": "中等",
2069+
"url": "https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/",
2070+
"path": "../../problemset/count-number-of-maximum-bitwise-or-subsets/README.md"
2071+
},
20622072
{
20632073
"id": 2047,
20642074
"title": {

assets/docs/CATEGORY.md

+7
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@
261261
| 138. [复制带随机指针的链表](../../problemset/copy-list-with-random-pointer/README.md) | 中等 |
262262
| 140. [单词拆分 II](../../problemset/word-break-2/README.md) | 困难 |
263263
| 1601. [最多可达成的换楼请求数目](../../problemset/maximum-number-of-achievable-transfer-requests/README.md) | 困难 |
264+
| 2044. [统计按位或能得到最大值的子集数目](../../problemset/count-number-of-maximum-bitwise-or-subsets/README.md) | 中等 |
264265

265266
##
266267

@@ -386,3 +387,9 @@
386387
| 题目 | 难度 |
387388
| ---- | ---- |
388389
| 1601. [最多可达成的换楼请求数目](../../problemset/maximum-number-of-achievable-transfer-requests/README.md) | 困难 |
390+
391+
## 位运算
392+
393+
| 题目 | 难度 |
394+
| ---- | ---- |
395+
| 2044. [统计按位或能得到最大值的子集数目](../../problemset/count-number-of-maximum-bitwise-or-subsets/README.md) | 中等 |

assets/docs/PROBLEMS.md

+2
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@
412412

413413
[2016. 增量元素之间的最大差值](../../problemset/maximum-difference-between-increasing-elements/README.md)
414414

415+
[2044. 统计按位或能得到最大值的子集数目](../../problemset/count-number-of-maximum-bitwise-or-subsets/README.md)
416+
415417
[2047. 句子中的有效单词数](../../problemset/number-of-valid-words-in-a-sentence/README.md)
416418

417419
[2049. 统计最高分的节点数目](../../problemset/count-nodes-with-the-highest-score/README.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# 统计按位或能得到最大值的子集数目
2+
3+
> 难度:中等
4+
>
5+
> https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/
6+
7+
## 题目
8+
9+
给你一个整数数组 `nums` ,请你找出 `nums` 子集 按位或 可能得到的** 最大值** ,并
10+
返回按位或能得到最大值的 **不同非空子集的数目**
11+
12+
如果数组 `a` 可以由数组 `b` 删除一些元素(或不删除)得到,则认为数组 `a` 是数组
13+
`b` 的一个 **子集** 。如果选中的元素下标位置不一样,则认为两个子集 **不同**
14+
15+
对数组 `a `执行 **按位或** ,结果等于 `a[0] OR a[1] OR ... OR a[a.length - 1]`
16+
下标从 0 开始)。
17+
18+
### 示例
19+
20+
#### 示例 1:
21+
22+
```
23+
输入:nums = [3,1]
24+
输出:2
25+
解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 :
26+
- [3]
27+
- [3,1]
28+
```
29+
30+
#### 示例 2:
31+
32+
```
33+
输入:nums = [2,2,2]
34+
输出:7
35+
解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。
36+
```
37+
38+
#### 示例 3:
39+
40+
```
41+
输入:nums = [3,2,1,5]
42+
输出:6
43+
解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :
44+
- [3,5]
45+
- [3,1,5]
46+
- [3,2,5]
47+
- [3,2,1,5]
48+
- [2,5]
49+
- [2,1,5]
50+
```
51+
52+
## 解题
53+
54+
### 回溯
55+
56+
```typescript
57+
/**
58+
* 回溯
59+
* @desc 时间复杂度 O(2^N) 空间复杂度 O(N)
60+
* @param nums
61+
*/
62+
export function countMaxOrSubsets(nums: number[]): number {
63+
const len = nums.length;
64+
let max = 0;
65+
let count = 0;
66+
dfs(0, 0);
67+
return count;
68+
69+
function dfs(pos: number, or: number) {
70+
if (pos === len) {
71+
if (or === max) count++;
72+
else if (or > max) {
73+
count = 1;
74+
max = or;
75+
}
76+
return;
77+
}
78+
79+
dfs(pos + 1, or | nums[pos]);
80+
dfs(pos + 1, or);
81+
}
82+
}
83+
```
84+
85+
### 位运算
86+
87+
```typescript
88+
/**
89+
* 位运算
90+
* @param nums
91+
*/
92+
export function countMaxOrSubsets2(nums: number[]): number {
93+
let max = 0;
94+
let count = 0;
95+
const len = nums.length;
96+
// len 长度的数组有 2^len - 1 种非空子集情况
97+
// 通过二进制来分别每一种情况
98+
for (let i = 0; i < 1 << len; i++) {
99+
let or = 0;
100+
for (let j = 0; j < len; j++) {
101+
// 判断当前的子集中,当前这个元素是否包含在里面
102+
if (((i >> j) & 1) === 1) {
103+
or |= nums[j];
104+
}
105+
}
106+
if (or > max) {
107+
max = or;
108+
count = 1;
109+
} else if (or === max) {
110+
count++;
111+
}
112+
}
113+
114+
return count;
115+
}
116+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { countMaxOrSubsets, countMaxOrSubsets2 } from '.';
2+
3+
describe('统计按位或能得到最大值的子集数目', () => {
4+
describe('回溯', () => {
5+
testCase(countMaxOrSubsets);
6+
});
7+
8+
describe('位运算', () => {
9+
testCase(countMaxOrSubsets2);
10+
});
11+
});
12+
13+
function testCase(fn: (nums: number[]) => number) {
14+
it('示例一', () => {
15+
const nums = [3, 1];
16+
const expected = 2;
17+
expect(fn(nums)).toBe(expected);
18+
});
19+
20+
it('示例二', () => {
21+
const nums = [2, 2, 2];
22+
const expected = 7;
23+
expect(fn(nums)).toBe(expected);
24+
});
25+
26+
it('示例三', () => {
27+
const nums = [3, 2, 1, 5];
28+
const expected = 6;
29+
expect(fn(nums)).toBe(expected);
30+
});
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* 回溯
3+
* @desc 时间复杂度 O(2^N) 空间复杂度 O(N)
4+
* @param nums
5+
*/
6+
export function countMaxOrSubsets(nums: number[]): number {
7+
const len = nums.length;
8+
let max = 0;
9+
let count = 0;
10+
dfs(0, 0);
11+
return count;
12+
13+
function dfs(pos: number, or: number) {
14+
if (pos === len) {
15+
if (or === max) count++;
16+
else if (or > max) {
17+
count = 1;
18+
max = or;
19+
}
20+
return;
21+
}
22+
23+
dfs(pos + 1, or | nums[pos]);
24+
dfs(pos + 1, or);
25+
}
26+
}
27+
28+
/**
29+
* 位运算
30+
* @param nums
31+
*/
32+
export function countMaxOrSubsets2(nums: number[]): number {
33+
let max = 0;
34+
let count = 0;
35+
const len = nums.length;
36+
// len 长度的数组有 2^len - 1 种非空子集情况
37+
// 通过二进制来分别每一种情况
38+
for (let i = 0; i < 1 << len; i++) {
39+
let or = 0;
40+
for (let j = 0; j < len; j++) {
41+
// 判断当前的子集中,当前这个元素是否包含在里面
42+
if (((i >> j) & 1) === 1) {
43+
or |= nums[j];
44+
}
45+
}
46+
if (or > max) {
47+
max = or;
48+
count = 1;
49+
} else if (or === max) {
50+
count++;
51+
}
52+
}
53+
54+
return count;
55+
}

0 commit comments

Comments
 (0)