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

[pull] main from itcharge:main #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
pull merged 129 commits into AlgorithmAndLeetCode:main from itcharge:main
May 27, 2022
Merged
Changes from 1 commit
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
edf6b32
Create Graph-Bellman-Ford.py
itcharge Mar 20, 2022
afb623a
Update 01.Hash-Table.md
itcharge Mar 21, 2022
5a18692
去除列表中重复题目
itcharge Mar 22, 2022
aeeb26a
更新目录章节列表
Mar 23, 2022
279255b
更新目录章节列表
Mar 23, 2022
a1f3ee0
更新题解列表
Mar 24, 2022
1b4be8a
Update 0001. 两数之和.md
Mar 28, 2022
de513d7
Update 01.Enumeration-Algorithm.md
Mar 28, 2022
19241f7
Update 01.Enumeration-Algorithm.md
Mar 29, 2022
dce7cd0
Update 01.Enumeration-Algorithm.md
Mar 29, 2022
b66ccbd
Update 01.Enumeration-Algorithm.md
Mar 29, 2022
092fa76
更新课程内容链接
Mar 29, 2022
1c77890
更新题解列表
Mar 30, 2022
1ebb2c1
更新课程内容链接
Mar 30, 2022
b6c3567
Update 01.Segment-Tree.md
Apr 1, 2022
5261ecd
Update 0078. 子集.md
Apr 1, 2022
d8949ea
更新题解列表
Apr 1, 2022
d49e419
Create 1450. 在既定时间做作业的学生人数.md
Apr 2, 2022
a12a916
Update LeetCode 解题报告空白.md
Apr 2, 2022
2a8e742
更新题解目录
Apr 2, 2022
8d7d466
Update 0204. 计数质数.md
Apr 6, 2022
c98b70d
Create 1925. 统计平方和三元组的数目.md
Apr 6, 2022
45b74c1
Create 0800. 相似 RGB 颜色.md
Apr 6, 2022
6f01d1c
更新题解列表
Apr 6, 2022
56cec98
Update 02.Algorithm-Complexity.md
Apr 6, 2022
c87996a
Update 0078. 子集.md
Apr 6, 2022
144761a
Update 0090. 子集 II.md
Apr 6, 2022
860f344
Update 剑指 Offer 57 - II. 和为s的连续正数序列.md
Apr 6, 2022
862f2f6
更新章节目录
Apr 7, 2022
c07e2ab
Update 03.LeetCode-Guide.md
Apr 8, 2022
cf216ed
Update 0091. 解码方法.md
Apr 8, 2022
2ce7012
Update 0198. 打家劫舍.md
Apr 8, 2022
c6ab45f
Update 0213. 打家劫舍 II.md
Apr 8, 2022
d616310
Update 1227. 飞机座位分配概率.md
Apr 8, 2022
664351c
Update 1486. 数组异或操作.md
Apr 8, 2022
ee79e53
Update 剑指 Offer II 089. 房屋偷盗.md
Apr 8, 2022
a93edaa
Update 剑指 Offer II 090. 环形房屋偷盗.md
Apr 8, 2022
d2c7af4
Update 0509. 斐波那契数.md
Apr 8, 2022
946591d
Update 0104. 二叉树的最大深度.md
Apr 8, 2022
6f82a91
更新文章代码格式
Apr 8, 2022
7575e44
Update 01.Recursive-Algorithm.md
Apr 8, 2022
31d9afe
Update 01.Recursive-Algorithm.md
Apr 8, 2022
e3c9bf5
Update 01.Recursive-Algorithm.md
Apr 8, 2022
17d0db8
Update 01.Recursive-Algorithm.md
Apr 11, 2022
c132bc5
更改题解标题格式
Apr 12, 2022
5c2dbe6
Update Array-MergeSort.py
Apr 14, 2022
2c373ef
Update 01.Divide-And-Conquer-Algorithm.md
Apr 14, 2022
56e57eb
更新公式格式
Apr 14, 2022
4c788aa
Update 01.Divide-And-Conquer-Algorithm.md
Apr 14, 2022
fbb04e2
Update 01.Recursive-Algorithm.md
itcharge Apr 18, 2022
3b11f52
Update 0303. 区域和检索 - 数组不可变.md
Apr 19, 2022
118b3e1
更新线段树模板
Apr 19, 2022
a0c5060
更新线段树模板
itcharge Apr 19, 2022
a59b2b0
更新题解列表
Apr 20, 2022
01e7dd9
Update 01.Backtracking-Algorithm.md
Apr 20, 2022
f5a441d
更新线段树模板
Apr 21, 2022
d9c77c0
Update 0303. 区域和检索 - 数组不可变.md
Apr 24, 2022
d5c8551
Update 0307. 区域和检索 - 数组可修改.md
Apr 24, 2022
0034d80
Update 0673. 最长递增子序列的个数.md
Apr 24, 2022
934b009
Update 1109. 航班预订统计.md
Apr 24, 2022
1fee32b
Update 1450. 在既定时间做作业的学生人数.md
Apr 24, 2022
ade2d16
Update 0370. 区间加法.md
Apr 24, 2022
a504a23
Create 1310. 子数组异或查询.md
Apr 24, 2022
d58ba3f
Create 0729. 我的日程安排表 I.md
Apr 24, 2022
4cca60b
Create 0731. 我的日程安排表 II.md
Apr 24, 2022
6a19d08
更新题解列表
Apr 24, 2022
4143b23
Update 01.Backtracking-Algorithm.md
Apr 26, 2022
679ac20
Update 01.Backtracking-Algorithm.md
Apr 26, 2022
3722ae9
Update 0046. 全排列.md
Apr 26, 2022
82ed40f
Update 0051. N 皇后.md
Apr 26, 2022
6bfe7db
Update 0078. 子集.md
Apr 26, 2022
7808a33
Update 01.Backtracking-Algorithm.md
Apr 26, 2022
0337985
更新课程信息
Apr 27, 2022
824e3fc
Update 01.Union-Find.md
May 5, 2022
8771e27
Update 01.Graph-Basic.md
May 6, 2022
0b278e3
Update 01.Union-Find.md
May 7, 2022
a55167d
Update 0547. 省份数量.md
May 9, 2022
a02c90f
Update 0990. 等式方程的可满足性.md
May 9, 2022
ffab9eb
更新 并查集文章
May 9, 2022
aa70ec9
更新并查集模板
May 9, 2022
1702217
更新并查集文章
May 9, 2022
76d3ccb
Update 01.Union-Find.md
May 10, 2022
39c00d3
更新贪心算法
May 10, 2022
4906387
Update 0455. 分发饼干.md
May 11, 2022
3fdca82
更新 并查集文章内容
May 11, 2022
ccef0ac
更新 贪心算法文章内容
May 11, 2022
c17114d
Update 0435. 无重叠区间.md
May 11, 2022
bd1586d
Update 0455. 分发饼干.md
May 11, 2022
8ede64f
更新 并查集文章内容
May 11, 2022
50ee50d
Update 01.Greedy-Algorithm.md
May 12, 2022
ed47e94
Create 1710. 卡车上的最大单元数.md
May 12, 2022
2058630
Update 0217. 存在重复元素.md
May 15, 2022
ad0d375
Update 0219. 存在重复元素 II.md
May 15, 2022
1bf455c
Update 0036. 有效的数独.md
May 15, 2022
556b42e
Update Course-Web-03.md
May 16, 2022
1ddf186
更新力扣新域名
May 18, 2022
836a4b2
Create 2276. 统计区间中的整数数目.md
May 18, 2022
7a87eb5
更新题解列表
May 18, 2022
f9ad233
Update 0005. 最长回文子串.md
May 19, 2022
96c49de
Create 1217. 玩筹码.md
May 19, 2022
63546bc
Create 1247. 交换字符使得字符串相同.md
May 19, 2022
f59d852
更新题解列表
May 19, 2022
c072756
Update 1247. 交换字符使得字符串相同.md
May 19, 2022
23a9161
Update 0189. 轮转数组.md
May 20, 2022
99359be
Create 1408. 数组中的字符串匹配.md
May 20, 2022
4a7ac52
Create 2156. 查找给定哈希值的子串.md
May 20, 2022
599bdf3
Update 02.String-Rabin-Karp.md
May 20, 2022
631f9ac
更新题解列表
May 20, 2022
cbd92c5
Update 2156. 查找给定哈希值的子串.md
May 20, 2022
aac56f7
Update 0189. 轮转数组.md
May 23, 2022
1eb829e
Create 1400. 构造 K 个回文字符串.md
itcharge May 23, 2022
676cf1d
Merge branch 'main' of https://github.com/itcharge/LeetCode-Py
itcharge May 23, 2022
7b2a477
Update 1400. 构造 K 个回文字符串.md
May 23, 2022
98f9927
Create 0921. 使括号有效的最少添加.md
May 23, 2022
92e3fa9
Create 1029. 两地调度.md
May 23, 2022
bed1393
Create 1605. 给定行和列的和求可行矩阵.md
May 23, 2022
d7e6d10
Create 0861. 翻转矩阵后的得分.md
May 23, 2022
4858672
更新题解列表
May 23, 2022
5779d8f
Update 0211. 添加与搜索单词 - 数据结构设计.md
May 24, 2022
1091fc3
Create 0846. 一手顺子.md
May 24, 2022
2d93c03
Create 1296. 划分数组为连续数字的集合.md
May 24, 2022
c5147f6
更新题解列表
May 24, 2022
c39e8ea
更新题解列表
May 25, 2022
841f1de
Create 0851. 喧闹和富有.md
May 25, 2022
c5c149e
更新题解列表
May 25, 2022
5723006
Create 0041. 缺失的第一个正数.md
May 26, 2022
e73e9ee
Update 0861. 翻转矩阵后的得分.md
May 26, 2022
b3ce2a4
Create 0201. 数字范围按位与.md
May 26, 2022
c00a40b
更新题解列表
May 26, 2022
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
Prev Previous commit
Next Next commit
Update 0090. 子集 II.md
  • Loading branch information
杨世超 committed Apr 6, 2022
commit 144761abcbf8bd21c4498cb54fd64b7e4c3a7452
96 changes: 91 additions & 5 deletions Solutions/0090. 子集 II.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,45 @@

## 题目大意

给定一个整数数组 `nums`,其中可能包含重复元素。
**描述**:给定一个整数数组 `nums`,其中可能包含重复元素。

要求:返回该数组所有可能的子集(幂集)。
**要求**:返回该数组所有可能的子集(幂集)。

注意:解集不能包含重复的子集。返回的解集中,子集可以按任意顺序排列。
**说明**:

- 解集不能包含重复的子集。返回的解集中,子集可以按任意顺序排列。
- 1ドル \le nums.length \le 10$。
- $-10 \le nums[i] \le 10$。

**示例**:

```Python
输入 nums = [1,2,2]
输出 [[],[1],[1,2],[1,2,2],[2],[2,2]]
```

## 解题思路

先对数组 `nums` 进行排序。回溯的时候,每次遍历从当前位置的下一个位置进行下一层遍历。同时通过判断当前元素是否和上一个元素相同可去除重复子集。如果相同的话,直接跳过。
### 思路 1:回溯算法

数组的每个元素都有两个选择:选与不选。

我们可以通过向当前子集数组中添加可选元素来表示选择该元素。也可以在当前递归结束之后,将之前添加的元素从当前子集数组中移除(也就是回溯)来表示不选择该元素。

因为数组中可能包含重复元素,所以我们可以先将数组排序,然后在回溯时,判断当前元素是否和上一个元素相同,如果相同,则直接跳过,从而去除重复元素。

## 代码
回溯算法解决这道题的步骤如下:

- 先对数组 `nums` 进行排序。
- 从第 `0` 个位置开始,调用 `backtrack` 方法进行深度优先搜索。
- 将当前子集数组 `sub_set` 添加到答案数组 `sub_sets` 中。
- 然后从当前位置开始,到数组结束为止,枚举出所有可选的元素。对于每一个可选元素:
- 如果当前元素与上一个元素相同,则跳过当前生成的子集。
- 将可选元素添加到当前子集数组 `sub_set` 中。
- 在选择该元素的情况下,继续递归考虑下一个元素。
- 进行回溯,撤销选择该元素。即从当前子集数组 `sub_set` 中移除之前添加的元素。

### 思路 1:回溯算法代码

```Python
class Solution:
Expand All @@ -36,3 +64,61 @@ class Solution:
return res
```

### 思路 2:二进制枚举

对于一个元素个数为 `n` 的集合 `nums` 来说,每一个位置上的元素都有选取和未选取两种状态。我们可以用数字 `1` 来表示选取该元素,用数字 `0` 来表示不选取该元素。

那么我们就可以用一个长度为 `n` 的二进制数来表示集合 `nums` 或者表示 `nums` 的子集。其中二进制的每一位数都对应了集合中某一个元素的选取状态。对于集合中第 `i` 个元素(`i` 从 `0` 开始编号)来说,二进制对应位置上的 `1` 代表该元素被选取,`0` 代表该元素未被选取。

举个例子来说明一下,比如长度为 `5` 的集合 `nums = {5, 4, 3, 2, 1}`,我们可以用一个长度为 `5` 的二进制数来表示该集合。

比如二进制数 `11111` 就表示选取集合的第 `0` 位、第 `1` 位、第 `2` 位、第 `3` 位、第 `4` 位元素,也就是集合 `{5, 4, 3, 2, 1}` ,即集合 `nums` 本身。如下表所示:

| 集合 nums 对应位置(下标) | 4 | 3 | 2 | 1 | 0 |
| :------------------------- | :--: | :--: | :--: | :--: | :--: |
| 对应选取状态 | 选取 | 选取 | 选取 | 选取 | 选取 |
| 二进制数对应位数 | 1 | 1 | 1 | 1 | 1 |

再比如二进制数 `10101` 就表示选取集合的第 `0` 位、第 `2` 位、第 `5` 位元素,也就是集合 `{5, 3, 1}`。如下表所示:

| 集合 nums 对应位置(下标) | 4 | 3 | 2 | 1 | 0 |
| :------------------------- | :--: | :----: | :--: | :----: | :--: |
| 对应选取状态 | 选取 | 未选取 | 选取 | 未选取 | 选取 |
| 二进制数对应位数 | 1 | 0 | 1 | 0 | 1 |

再比如二进制数 `01001` 就表示选取集合的第 `0` 位、第 `3` 位元素,也就是集合 `{5, 2}`。如下标所示:

| 集合 nums 对应位置(下标) | 4 | 3 | 2 | 1 | 0 |
| :------------------------- | :----: | :--: | :----: | :----: | :--: |
| 对应选取状态 | 未选取 | 选取 | 未选取 | 未选取 | 选取 |
| 二进制数对应位数 | 0 | 1 | 0 | 0 | 1 |

通过上面的例子我们可以得到启发:对于长度为 `5` 的集合 `nums` 来说,我们只需要从 `00000` ~ `11111` 枚举一次(对应十进制为 0ドル \sim 2^4 - 1$)即可得到长度为 `5` 的集合 `S` 的所有子集。

我们将上面的例子拓展到长度为 `n` 的集合 `nums`。可以总结为:

- 对于长度为 `5` 的集合 `nums` 来说,只需要枚举 0ドル \sim 2^n - 1$(共 2ドル^n$ 种情况),即可得到所有的子集。

因为数组中可能包含重复元素,所以我们可以先对数组进行排序。然后在枚举过程中,如果发现当前元素和上一个元素相同,则直接跳过当前生层的子集,从而去除重复元素。

### 思路 2:二进制枚举代码

```Python
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n = len(nums) # n 为集合 nums 的元素个数
sub_sets = [] # sub_sets 用于保存所有子集
for i in range(1 << n): # 枚举 0 ~ 2^n - 1
sub_set = [] # sub_set 用于保存当前子集
flag = True # flag 用于判断重复元素
for j in range(n): # 枚举第 i 位元素
if i >> j & 1: # 如果第 i 为元素对应二进制位为 1,则表示选取该元素
if j > 0 and (i >> (j - 1) & 1) == 0 and nums[j] == nums[j - 1]:
flag = False # 如果出现重复元素,则跳过当前生成的子集
break
sub_set.append(nums[j]) # 将选取的元素加入到子集 sub_set 中
if flag:
sub_sets.append(sub_set) # 将子集 sub_set 加入到所有子集数组 sub_sets 中
return sub_sets # 返回所有子集
```

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