forked from itcharge/AlgoNote
-
Notifications
You must be signed in to change notification settings - Fork 0
[pull] main from itcharge:main #92
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
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
Solutions/0847. 访问所有节点的最短路径.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# [0847. 访问所有节点的最短路径](https://leetcode.cn/problems/shortest-path-visiting-all-nodes/) | ||
|
||
- 标签:位运算、广度优先搜索、图、动态规划、状态压缩 | ||
- 难度:困难 | ||
|
||
## 题目大意 | ||
|
||
**描述**:存在一个由 $n$ 个节点组成的无向连通图,图中节点编号为 1ドル \sim n - 1$。现在给定一个数组 $graph$ 表示这个图。其中,$graph[i]$ 是一个列表,由所有与节点 $i$ 直接相连的节点组成。 | ||
|
||
**要求**:返回能够访问所有节点的最短路径长度。可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。 | ||
|
||
**说明**: | ||
|
||
- $n == graph.length$。 | ||
- 1ドル \le n \le 12$。 | ||
- 0ドル \le graph[i].length < n$。 | ||
- $graph[i]$ 不包含 $i$。 | ||
- 如果 $graph[a]$ 包含 $b,ドル那么 $graph[b]$ 也包含 $a$。 | ||
- 输入的图总是连通图。 | ||
|
||
**示例**: | ||
|
||
- 示例 1: | ||
|
||
 | ||
|
||
```Python | ||
输入:graph = [[1,2,3],[0],[0],[0]] | ||
输出:4 | ||
解释:一种可能的路径为 [1,0,2,0,3] | ||
``` | ||
|
||
- 示例 2: | ||
|
||
 | ||
|
||
```Python | ||
输入:graph = [[1],[0,2,4],[1,3,4],[2],[1,2]] | ||
输出:4 | ||
解释:一种可能的路径为 [0,1,4,2,3] | ||
``` | ||
|
||
## 解题思路 | ||
|
||
### 思路 1:状态压缩 + 广度优先搜索 | ||
|
||
题目需要求解的是「能够访问所有节点的最短路径长度」,并且每个节点都可以作为起始点。 | ||
|
||
如果对于一个特定的起点,我们可以将该起点放入队列中,然后对其进行广度优先搜索,并使用访问数组 $visited$ 标记访问过的节点,直到所有节点都已经访问过时,返回路径长度即为「从某点开始出发,所能够访问所有节点的最短路径长度」。 | ||
|
||
而本题中,每个节点都可以作为起始点,则我们可以直接将所有节点放入队列中,然后对所有节点进行广度优先搜索。 | ||
|
||
因为本题中节点数目 $n$ 的范围为 $[1, 12],ドル所以我们可以采用「状态压缩」的方式,标记节点的访问情况。每个点的初始状态可以表示为 `(u, 1 << u)`。当状态 $state == 1 << n - 1$ 时,表示所有节点都已经访问过了,此时返回其对应路径长度即为「能够访问所有节点的最短路径长度」。 | ||
|
||
为了方便在广度优先搜索的同事,记录当前的「路径长度」以及「节点的访问情况」。我们可以使用一个三元组 $(u, state, dist)$ 来表示当前节点情况,其中: | ||
|
||
- $u$:表示当前节点编号。 | ||
- $state$:一个 $n$ 位的二进制数,表示 $n$ 个节点的访问情况。$state$ 第 $i$ 位为 0ドル$ 时表示未访问过,$state$ 第 $i$ 位为 1ドル$ 时表示访问过。 | ||
- $dist$ 表示当前的「路径长度」。 | ||
|
||
同时为了避免重复搜索同一个节点 $u$ 以及相同节点的访问情况,我们可以使用集合记录 $(u, state)$ 是否已经被搜索过。 | ||
|
||
整个算法步骤如下: | ||
|
||
1. 将所有节点的 `(节点编号, 起始状态, 路径长度)` 作为三元组存入队列,并使用集合 $visited$ 记录所有节点的访问情况。 | ||
2. 对所有点开始进行广度优先搜索: | ||
1. 从队列中弹出队头节点。 | ||
2. 判断节点的当前状态,如果所有节点都已经访问过,则返回答案。 | ||
3. 如果没有全访问过,则遍历当前节点的邻接节点。 | ||
4. 将邻接节点的访问状态标记为访问过。 | ||
5. 如果节点即当前路径没有访问过,则加入队列继续遍历,并标记为访问过。 | ||
3. 重复进行第 2ドル$ 步,直到队列为空。 | ||
|
||
### 思路 1:代码 | ||
|
||
```Python | ||
import collections | ||
|
||
|
||
class Solution: | ||
def shortestPathLength(self, graph: List[List[int]]) -> int: | ||
size = len(graph) | ||
|
||
queue = collections.deque([]) | ||
visited = set() | ||
for u in range(size): | ||
queue.append((u, 1 << u, 0)) # 将 (节点编号, 起始状态, 路径长度) 存入队列 | ||
visited.add((u, 1 << u)) # 标记所有节点的节点编号,以及当前状态 | ||
|
||
while queue: # 对所有点开始进行广度优先搜索 | ||
u, state, dist = queue.popleft() # 弹出队头节点 | ||
if state == (1 << size) - 1: # 所有节点都访问完,返回答案 | ||
return dist | ||
for v in graph[u]: # 遍历邻接节点 | ||
next_state = state | (1 << v) # 标记邻接节点的访问状态 | ||
if (v, next_state) not in visited: # 如果节点即当前路径没有访问过,则加入队列继续遍历,并标记为访问过 | ||
queue.append((v, next_state, dist + 1)) | ||
visited.add((v, next_state)) | ||
|
||
return 0 | ||
``` | ||
|
||
### 思路 1:复杂度分析 | ||
|
||
- **时间复杂度**:$O(n^2 \times 2^n),ドル其中 $n$ 为图的节点数量。 | ||
- **空间复杂度**:$O(n \times 2^n)$。 | ||
|
104 changes: 104 additions & 0 deletions
Solutions/1994. 好子集的数目.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# [1994. 好子集的数目](https://leetcode.cn/problems/the-number-of-good-subsets/) | ||
|
||
- 标签:位运算、数组、数学、动态规划、状态压缩 | ||
- 难度:困难 | ||
|
||
## 题目大意 | ||
|
||
**描述**:给定一个整数数组 $nums$。 | ||
|
||
**要求**:返回 $nums$ 中不同的好子集的数目对 10ドル^9 + 7$ 取余的结果。 | ||
|
||
**说明**: | ||
|
||
- **子集**:通过删除 $nums$ 中一些(可能一个都不删除,也可能全部都删除)元素后剩余元素组成的数组。如果两个子集删除的下标不同,那么它们被视为不同的子集。 | ||
|
||
- **好子集**:如果 $nums$ 的一个子集中,所有元素的乘积可以表示为一个或多个互不相同的质数的乘积,那么我们称它为好子集。 | ||
- 比如,如果 `nums = [1, 2, 3, 4]`: | ||
- `[2, 3]` ,`[1, 2, 3]` 和 `[1, 3]` 是好子集,乘积分别为 `6 = 2*3` ,`6 = 2*3` 和 `3 = 3` 。 | ||
- `[1, 4]` 和 `[4]` 不是好子集,因为乘积分别为 `4 = 2*2` 和 `4 = 2*2` 。 | ||
|
||
- 1ドル \le nums.length \le 10^5$。 | ||
- 1ドル \le nums[i] \le 30$。 | ||
|
||
**示例**: | ||
|
||
- 示例 1: | ||
|
||
```Python | ||
输入:nums = [1,2,3,4] | ||
输出:6 | ||
解释:好子集为: | ||
- [1,2]:乘积为 2 ,可以表示为质数 2 的乘积。 | ||
- [1,2,3]:乘积为 6 ,可以表示为互不相同的质数 2 和 3 的乘积。 | ||
- [1,3]:乘积为 3 ,可以表示为质数 3 的乘积。 | ||
- [2]:乘积为 2 ,可以表示为质数 2 的乘积。 | ||
- [2,3]:乘积为 6 ,可以表示为互不相同的质数 2 和 3 的乘积。 | ||
- [3]:乘积为 3 ,可以表示为质数 3 的乘积。 | ||
``` | ||
|
||
- 示例 2: | ||
|
||
```Python | ||
输入:nums = [4,2,3,15] | ||
输出:5 | ||
解释:好子集为: | ||
- [2]:乘积为 2 ,可以表示为质数 2 的乘积。 | ||
- [2,3]:乘积为 6 ,可以表示为互不相同质数 2 和 3 的乘积。 | ||
- [2,15]:乘积为 30 ,可以表示为互不相同质数 2,3 和 5 的乘积。 | ||
- [3]:乘积为 3 ,可以表示为质数 3 的乘积。 | ||
- [15]:乘积为 15 ,可以表示为互不相同质数 3 和 5 的乘积。 | ||
``` | ||
|
||
## 解题思路 | ||
|
||
### 思路 1:状态压缩 DP | ||
|
||
|
||
|
||
### 思路 1:代码 | ||
|
||
```Python | ||
class Solution: | ||
def numberOfGoodSubsets(self, nums: List[int]) -> int: | ||
MOD = 10 ** 9 + 7 | ||
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] | ||
|
||
cnts = Counter(nums) | ||
dp = [0 for _ in range(1 << len(primes))] | ||
dp[0] = pow(2, cnts[1], MOD) | ||
|
||
for num, cnt in cnts.items(): # 遍历 nums 中所有数及其频数 | ||
if num == 1: # 跳过 1 | ||
continue | ||
flag = True # 判断当前子集是否满足互不相同的质数相乘 | ||
cur_num = num | ||
cur_state = 0 | ||
for i, prime in enumerate(primes): | ||
cur_cnt = 0 | ||
while cur_num % prime == 0: | ||
cur_cnt += 1 | ||
cur_state = cur_state | 1 << i | ||
cur_num //= prime | ||
if cur_cnt > 1: | ||
flag = False | ||
break | ||
if not flag: | ||
continue | ||
|
||
for state in range(1 << len(primes)): | ||
# | ||
if state & cur_state == 0: | ||
dp[state | cur_state] = (dp[state | cur_state] + dp[state] * cnts[num]) % MOD | ||
|
||
ans = 0 | ||
for i in range(1, 1 << len(primes)): | ||
ans = (ans + dp[i]) % MOD | ||
|
||
return ans | ||
``` | ||
|
||
### 思路 1:复杂度分析 | ||
|
||
- **时间复杂度**: | ||
- **空间复杂度**: |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.