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 2e06107

Browse files
committed
Create 2246. 相邻字符不同的最长路径.md
1 parent de485bc commit 2e06107

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# [2246. 相邻字符不同的最长路径](https://leetcode.cn/problems/longest-path-with-different-adjacent-characters/)
2+
3+
- 标签:树、深度优先搜索、图、拓扑排序、数组、字符串
4+
- 难度:困难
5+
6+
## 题目大意
7+
8+
**描述**:给定一个长度为 $n$ 的数组 $parent$ 来表示一棵树(即一个连通、无向、无环图)。该树的节点编号为 0ドル \sim n - 1,ドル共 $n$ 个节点,其中根节点的编号为 0ドル$。其中 $parent[i]$ 表示节点 $i$ 的父节点,由于节点 0ドル$ 是根节点,所以 $parent[0] == -1$。再给定一个长度为 $n$ 的字符串,其中 $s[i]$ 表示分配给节点 $i$ 的字符。
9+
10+
**要求**:找出路径上任意一对相邻节点都没有分配到相同字符的最长路径,并返回该路径的长度。
11+
12+
**说明**:
13+
14+
- $n == parent.length == s.length$。
15+
- 1ドル \le n \le 10^5$。
16+
- 对所有 $i \ge 1$ ,0ドル \le parent[i] \le n - 1$ 均成立。
17+
- $parent[0] == -1$。
18+
- $parent$ 表示一棵有效的树。
19+
- $s$ 仅由小写英文字母组成。
20+
21+
**示例**:
22+
23+
- 示例 1:
24+
25+
![](https://assets.leetcode.com/uploads/2022/03/25/testingdrawio.png)
26+
27+
```Python
28+
输入:parent = [-1,0,0,1,1,2], s = "abacbe"
29+
输出:3
30+
解释:任意一对相邻节点字符都不同的最长路径是:0 -> 1 -> 3 。该路径的长度是 3 ,所以返回 3
31+
可以证明不存在满足上述条件且比 3 更长的路径。
32+
```
33+
34+
- 示例 2:
35+
36+
![](https://assets.leetcode.com/uploads/2022/03/25/graph2drawio.png)
37+
38+
```Python
39+
输入:parent = [-1,0,0,0], s = "aabc"
40+
输出:3
41+
解释:任意一对相邻节点字符都不同的最长路径是:2 -> 0 -> 3 。该路径的长度为 3 ,所以返回 3
42+
```
43+
44+
## 解题思路
45+
46+
### 思路 1:树形 DP + 深度优先搜索
47+
48+
因为题目给定的是表示父子节点的 $parent$ 数组,为了方便递归遍历相邻节点,我们可以根据 $partent$ 数组,建立一个由父节点指向子节点的有向图 $graph$。
49+
50+
如果不考虑相邻节点是否为相同字符这一条件,那么这道题就是在求树的直径(树的最长路径长度)中的节点个数。
51+
52+
对于根节点为 $u$ 的树来说:
53+
54+
1. 如果其最长路径经过根节点 $u,ドル则 $最长路径长度 = 某子树中的最长路径长度 + 另一子树中的最长路径长度 + 1$。
55+
2. 如果其最长路径不经过根节点 $u,ドル则 $最长路径长度 = 某个子树中的最长路径长度$。
56+
57+
即:$最长路径长度 = max(某子树中的最长路径长度 + 另一子树中的最长路径长度 + 1, \quad 某个子树中的最长路径长度)$。
58+
59+
对此,我们可以使用深度优先搜索递归遍历 $u$ 的所有相邻节点 $v,ドル并在递归遍历的同时,维护一个全局最大路径和变量 $ans,ドル以及当前节点 $u$ 的最大路径长度变量 $u\underline{}len$。
60+
61+
1. 先计算出从相邻节点 $v$ 出发的最长路径长度 $v\underline{}len$。
62+
2. 更新维护全局最长路径长度为 $self.ans = max(self.ans, \quad u\underline{}len + v\underline{}len + 1)$。
63+
3. 更新维护当前节点 $u$ 的最长路径长度为 $u\underline{}len = max(u\underline{}len, \quad v\underline{}len + 1)$。
64+
65+
因为题目限定了「相邻节点字符不同」,所以在更新全局最长路径长度和当前节点 $u$ 的最长路径长度时,我们需要判断一下节点 $u$ 与相邻节点 $v$ 的字符是否相同,只有在字符不同的条件下,才能够更新维护。
66+
67+
最后,因为题目要求的是树的直径(树的最长路径长度)中的节点个数,而:$路径的节点 = 路径长度 + 1,ドル所以最后我们返回 $self.ans + 1$ 作为答案。
68+
69+
### 思路 1:代码
70+
71+
```Python
72+
class Solution:
73+
def __init__(self):
74+
self.ans = 0
75+
76+
def dfs(self, graph, s, u):
77+
u_len = 0 # u 节点的最大路径长度
78+
for v in graph[u]: # 遍历 u 节点的相邻节点
79+
v_len = self.dfs(graph, s, v) # 相邻节点的最大路径长度
80+
if s[u] != s[v]: # 相邻节点字符不同
81+
self.ans = max(self.ans, u_len + v_len + 1) # 维护最大路径长度
82+
u_len = max(u_len, v_len + 1) # 更新 u 节点的最大路径长度
83+
return u_len # 返回 u 节点的最大路径长度
84+
85+
def longestPath(self, parent: List[int], s: str) -> int:
86+
size = len(parent)
87+
88+
# 根据 parent 数组,建立有向图
89+
graph = [[] for _ in range(size)]
90+
for i in range(1, size):
91+
graph[parent[i]].append(i)
92+
93+
self.dfs(graph, s, 0)
94+
95+
return self.ans + 1
96+
```
97+
98+
### 思路 1:复杂度分析
99+
100+
- **时间复杂度**:$O(n),ドル其中 $n$ 是树的节点数目。
101+
- **空间复杂度**:$O(n)$

0 commit comments

Comments
(0)

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