forked from itcharge/AlgoNote
-
Notifications
You must be signed in to change notification settings - Fork 0
[pull] main from itcharge:main #83
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
Show all changes
3 commits
Select commit
Hold shift + click to select a range
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
101 changes: 101 additions & 0 deletions
Solutions/2246. 相邻字符不同的最长路径.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,101 @@ | ||
# [2246. 相邻字符不同的最长路径](https://leetcode.cn/problems/longest-path-with-different-adjacent-characters/) | ||
|
||
- 标签:树、深度优先搜索、图、拓扑排序、数组、字符串 | ||
- 难度:困难 | ||
|
||
## 题目大意 | ||
|
||
**描述**:给定一个长度为 $n$ 的数组 $parent$ 来表示一棵树(即一个连通、无向、无环图)。该树的节点编号为 0ドル \sim n - 1,ドル共 $n$ 个节点,其中根节点的编号为 0ドル$。其中 $parent[i]$ 表示节点 $i$ 的父节点,由于节点 0ドル$ 是根节点,所以 $parent[0] == -1$。再给定一个长度为 $n$ 的字符串,其中 $s[i]$ 表示分配给节点 $i$ 的字符。 | ||
|
||
**要求**:找出路径上任意一对相邻节点都没有分配到相同字符的最长路径,并返回该路径的长度。 | ||
|
||
**说明**: | ||
|
||
- $n == parent.length == s.length$。 | ||
- 1ドル \le n \le 10^5$。 | ||
- 对所有 $i \ge 1$ ,0ドル \le parent[i] \le n - 1$ 均成立。 | ||
- $parent[0] == -1$。 | ||
- $parent$ 表示一棵有效的树。 | ||
- $s$ 仅由小写英文字母组成。 | ||
|
||
**示例**: | ||
|
||
- 示例 1: | ||
|
||
 | ||
|
||
```Python | ||
输入:parent = [-1,0,0,1,1,2], s = "abacbe" | ||
输出:3 | ||
解释:任意一对相邻节点字符都不同的最长路径是:0 -> 1 -> 3 。该路径的长度是 3 ,所以返回 3。 | ||
可以证明不存在满足上述条件且比 3 更长的路径。 | ||
``` | ||
|
||
- 示例 2: | ||
|
||
 | ||
|
||
```Python | ||
输入:parent = [-1,0,0,0], s = "aabc" | ||
输出:3 | ||
解释:任意一对相邻节点字符都不同的最长路径是:2 -> 0 -> 3 。该路径的长度为 3 ,所以返回 3。 | ||
``` | ||
|
||
## 解题思路 | ||
|
||
### 思路 1:树形 DP + 深度优先搜索 | ||
|
||
因为题目给定的是表示父子节点的 $parent$ 数组,为了方便递归遍历相邻节点,我们可以根据 $partent$ 数组,建立一个由父节点指向子节点的有向图 $graph$。 | ||
|
||
如果不考虑相邻节点是否为相同字符这一条件,那么这道题就是在求树的直径(树的最长路径长度)中的节点个数。 | ||
|
||
对于根节点为 $u$ 的树来说: | ||
|
||
1. 如果其最长路径经过根节点 $u,ドル则 $最长路径长度 = 某子树中的最长路径长度 + 另一子树中的最长路径长度 + 1$。 | ||
2. 如果其最长路径不经过根节点 $u,ドル则 $最长路径长度 = 某个子树中的最长路径长度$。 | ||
|
||
即:$最长路径长度 = max(某子树中的最长路径长度 + 另一子树中的最长路径长度 + 1, \quad 某个子树中的最长路径长度)$。 | ||
|
||
对此,我们可以使用深度优先搜索递归遍历 $u$ 的所有相邻节点 $v,ドル并在递归遍历的同时,维护一个全局最大路径和变量 $ans,ドル以及当前节点 $u$ 的最大路径长度变量 $u\underline{}len$。 | ||
|
||
1. 先计算出从相邻节点 $v$ 出发的最长路径长度 $v\underline{}len$。 | ||
2. 更新维护全局最长路径长度为 $self.ans = max(self.ans, \quad u\underline{}len + v\underline{}len + 1)$。 | ||
3. 更新维护当前节点 $u$ 的最长路径长度为 $u\underline{}len = max(u\underline{}len, \quad v\underline{}len + 1)$。 | ||
|
||
因为题目限定了「相邻节点字符不同」,所以在更新全局最长路径长度和当前节点 $u$ 的最长路径长度时,我们需要判断一下节点 $u$ 与相邻节点 $v$ 的字符是否相同,只有在字符不同的条件下,才能够更新维护。 | ||
|
||
最后,因为题目要求的是树的直径(树的最长路径长度)中的节点个数,而:$路径的节点 = 路径长度 + 1,ドル所以最后我们返回 $self.ans + 1$ 作为答案。 | ||
|
||
### 思路 1:代码 | ||
|
||
```Python | ||
class Solution: | ||
def __init__(self): | ||
self.ans = 0 | ||
|
||
def dfs(self, graph, s, u): | ||
u_len = 0 # u 节点的最大路径长度 | ||
for v in graph[u]: # 遍历 u 节点的相邻节点 | ||
v_len = self.dfs(graph, s, v) # 相邻节点的最大路径长度 | ||
if s[u] != s[v]: # 相邻节点字符不同 | ||
self.ans = max(self.ans, u_len + v_len + 1) # 维护最大路径长度 | ||
u_len = max(u_len, v_len + 1) # 更新 u 节点的最大路径长度 | ||
return u_len # 返回 u 节点的最大路径长度 | ||
|
||
def longestPath(self, parent: List[int], s: str) -> int: | ||
size = len(parent) | ||
|
||
# 根据 parent 数组,建立有向图 | ||
graph = [[] for _ in range(size)] | ||
for i in range(1, size): | ||
graph[parent[i]].append(i) | ||
|
||
self.dfs(graph, s, 0) | ||
|
||
return self.ans + 1 | ||
``` | ||
|
||
### 思路 1:复杂度分析 | ||
|
||
- **时间复杂度**:$O(n),ドル其中 $n$ 是树的节点数目。 | ||
- **空间复杂度**:$O(n)$ |
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.