Skip to content

Commit e139604

Browse files
committed
feat: add solutions to lc problem: No.1483
No.1483.Kth Ancestor of a Tree Node
1 parent 2c88050 commit e139604

File tree

6 files changed

+459
-2
lines changed

6 files changed

+459
-2
lines changed

solution/1400-1499/1483.Kth Ancestor of a Tree Node/README.md

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,189 @@ treeAncestor.getKthAncestor(6, 3); // 返回 -1 因为不存在满足要求的
5555

5656
<!-- 这里可写通用的实现逻辑 -->
5757

58+
**方法一:动态规划 + 倍增**
59+
60+
题目要我们寻找节点 `node` 的第 $k$ 个祖先节点,如果暴力求解,需要从 `node` 开始向上遍历 $k$ 次,时间复杂度为 $O(k)$,显然会超时。
61+
62+
我们可以使用动态规划的思想,结合倍增的思想来处理。
63+
64+
我们定义 $p[i][j]$ 表示节点 $i$ 的第 $2^j$ 个祖先节点,即 $p[i][j]$ 表示节点 $i$ 向上走 $2^j$ 步的节点。那么我们可以得到状态转移方程:
65+
66+
$$
67+
p[i][j] = p[p[i][j-1]][j-1]
68+
$$
69+
70+
即:要想找到节点 $i$ 的第 $2^j$ 个祖先节点,我们可以先找到节点 $i$ 的第 $2^{j-1}$ 个祖先节点,然后再找到该节点的第 $2^{j-1}$ 个祖先节点即可。所以,我们要找到每个节点的距离为 $2^j$ 的祖先节点,直到达到树的最大高度。
71+
72+
之后对于每次查询,我们可以把 $k$ 拆成二进制的表示形式,然后根据二进制中 $1$ 的位置,累计向上查询,最终得到节点 $node$ 的第 $k$ 个祖先节点。
73+
74+
时间复杂度:初始化为 $O(n \times \log n)$,查询为 $O(\log n)$。空间复杂度:$O(n \times \log n)$。其中 $n$ 为树的节点数。
75+
5876
<!-- tabs:start -->
5977

6078
### **Python3**
6179

6280
<!-- 这里可写当前语言的特殊实现逻辑 -->
6381

6482
```python
65-
83+
class TreeAncestor:
84+
85+
def __init__(self, n: int, parent: List[int]):
86+
self.p = [[-1] * 18 for _ in range(n)]
87+
for i, fa in enumerate(parent):
88+
self.p[i][0] = fa
89+
for i in range(n):
90+
for j in range(1, 18):
91+
if self.p[i][j - 1] == -1:
92+
continue
93+
self.p[i][j] = self.p[self.p[i][j - 1]][j - 1]
94+
95+
def getKthAncestor(self, node: int, k: int) -> int:
96+
for i in range(17, -1, -1):
97+
if k >> i & 1:
98+
node = self.p[node][i]
99+
if node == -1:
100+
break
101+
return node
102+
103+
104+
# Your TreeAncestor object will be instantiated and called as such:
105+
# obj = TreeAncestor(n, parent)
106+
# param_1 = obj.getKthAncestor(node,k)
66107
```
67108

68109
### **Java**
69110

70111
<!-- 这里可写当前语言的特殊实现逻辑 -->
71112

72113
```java
114+
class TreeAncestor {
115+
private int[][] p;
116+
117+
public TreeAncestor(int n, int[] parent) {
118+
p = new int[n][18];
119+
for (var e : p) {
120+
Arrays.fill(e, -1);
121+
}
122+
for (int i = 0; i < n; ++i) {
123+
p[i][0] = parent[i];
124+
}
125+
for (int i = 0; i < n; ++i) {
126+
for (int j = 1; j < 18; ++j) {
127+
if (p[i][j - 1] == -1) {
128+
continue;
129+
}
130+
p[i][j] = p[p[i][j - 1]][j - 1];
131+
}
132+
}
133+
}
134+
135+
public int getKthAncestor(int node, int k) {
136+
for (int i = 17; i >= 0; --i) {
137+
if (((k >> i) & 1) == 1) {
138+
node = p[node][i];
139+
if (node == -1) {
140+
break;
141+
}
142+
}
143+
}
144+
return node;
145+
}
146+
}
147+
148+
/**
149+
* Your TreeAncestor object will be instantiated and called as such:
150+
* TreeAncestor obj = new TreeAncestor(n, parent);
151+
* int param_1 = obj.getKthAncestor(node,k);
152+
*/
153+
```
154+
155+
### **C++**
156+
157+
```cpp
158+
class TreeAncestor {
159+
public:
160+
TreeAncestor(int n, vector<int>& parent) {
161+
p = vector<vector<int>>(n, vector<int>(18, -1));
162+
for (int i = 0; i < n; ++i) {
163+
p[i][0] = parent[i];
164+
}
165+
for (int i = 0; i < n; ++i) {
166+
for (int j = 1; j < 18; ++j) {
167+
if (p[i][j - 1] == -1) {
168+
continue;
169+
}
170+
p[i][j] = p[p[i][j - 1]][j - 1];
171+
}
172+
}
173+
}
174+
175+
int getKthAncestor(int node, int k) {
176+
for (int i = 17; ~i; --i) {
177+
if (k >> i & 1) {
178+
node = p[node][i];
179+
if (node == -1) {
180+
break;
181+
}
182+
}
183+
}
184+
return node;
185+
}
186+
187+
private:
188+
vector<vector<int>> p;
189+
};
190+
191+
/**
192+
* Your TreeAncestor object will be instantiated and called as such:
193+
* TreeAncestor* obj = new TreeAncestor(n, parent);
194+
* int param_1 = obj->getKthAncestor(node,k);
195+
*/
196+
```
73197

198+
### **Go**
199+
200+
```go
201+
type TreeAncestor struct {
202+
p [][18]int
203+
}
204+
205+
func Constructor(n int, parent []int) TreeAncestor {
206+
p := make([][18]int, n)
207+
for i, fa := range parent {
208+
p[i][0] = fa
209+
for j := 1; j < 18; j++ {
210+
p[i][j] = -1
211+
}
212+
}
213+
for i := range p {
214+
for j := 1; j < 18; j++ {
215+
if p[i][j-1] == -1 {
216+
continue
217+
}
218+
p[i][j] = p[p[i][j-1]][j-1]
219+
}
220+
}
221+
return TreeAncestor{p}
222+
}
223+
224+
func (this *TreeAncestor) GetKthAncestor(node int, k int) int {
225+
for i := 17; i >= 0; i-- {
226+
if k>>i&1 == 1 {
227+
node = this.p[node][i]
228+
if node == -1 {
229+
break
230+
}
231+
}
232+
}
233+
return node
234+
}
235+
236+
/**
237+
* Your TreeAncestor object will be instantiated and called as such:
238+
* obj := Constructor(n, parent);
239+
* param_1 := obj.GetKthAncestor(node,k);
240+
*/
74241
```
75242

76243
### **...**

solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,162 @@ treeAncestor.getKthAncestor(6, 3); // returns -1 because there is no such ancest
5050
### **Python3**
5151

5252
```python
53-
53+
class TreeAncestor:
54+
55+
def __init__(self, n: int, parent: List[int]):
56+
self.p = [[-1] * 18 for _ in range(n)]
57+
for i, fa in enumerate(parent):
58+
self.p[i][0] = fa
59+
for i in range(n):
60+
for j in range(1, 18):
61+
if self.p[i][j - 1] == -1:
62+
continue
63+
self.p[i][j] = self.p[self.p[i][j - 1]][j - 1]
64+
65+
def getKthAncestor(self, node: int, k: int) -> int:
66+
for i in range(17, -1, -1):
67+
if k >> i & 1:
68+
node = self.p[node][i]
69+
if node == -1:
70+
break
71+
return node
72+
73+
74+
# Your TreeAncestor object will be instantiated and called as such:
75+
# obj = TreeAncestor(n, parent)
76+
# param_1 = obj.getKthAncestor(node,k)
5477
```
5578

5679
### **Java**
5780

5881
```java
82+
class TreeAncestor {
83+
private int[][] p;
84+
85+
public TreeAncestor(int n, int[] parent) {
86+
p = new int[n][18];
87+
for (var e : p) {
88+
Arrays.fill(e, -1);
89+
}
90+
for (int i = 0; i < n; ++i) {
91+
p[i][0] = parent[i];
92+
}
93+
for (int i = 0; i < n; ++i) {
94+
for (int j = 1; j < 18; ++j) {
95+
if (p[i][j - 1] == -1) {
96+
continue;
97+
}
98+
p[i][j] = p[p[i][j - 1]][j - 1];
99+
}
100+
}
101+
}
102+
103+
public int getKthAncestor(int node, int k) {
104+
for (int i = 17; i >= 0; --i) {
105+
if (((k >> i) & 1) == 1) {
106+
node = p[node][i];
107+
if (node == -1) {
108+
break;
109+
}
110+
}
111+
}
112+
return node;
113+
}
114+
}
115+
116+
/**
117+
* Your TreeAncestor object will be instantiated and called as such:
118+
* TreeAncestor obj = new TreeAncestor(n, parent);
119+
* int param_1 = obj.getKthAncestor(node,k);
120+
*/
121+
```
122+
123+
### **C++**
124+
125+
```cpp
126+
class TreeAncestor {
127+
public:
128+
TreeAncestor(int n, vector<int>& parent) {
129+
p = vector<vector<int>>(n, vector<int>(18, -1));
130+
for (int i = 0; i < n; ++i) {
131+
p[i][0] = parent[i];
132+
}
133+
for (int i = 0; i < n; ++i) {
134+
for (int j = 1; j < 18; ++j) {
135+
if (p[i][j - 1] == -1) {
136+
continue;
137+
}
138+
p[i][j] = p[p[i][j - 1]][j - 1];
139+
}
140+
}
141+
}
142+
143+
int getKthAncestor(int node, int k) {
144+
for (int i = 17; ~i; --i) {
145+
if (k >> i & 1) {
146+
node = p[node][i];
147+
if (node == -1) {
148+
break;
149+
}
150+
}
151+
}
152+
return node;
153+
}
154+
155+
private:
156+
vector<vector<int>> p;
157+
};
158+
159+
/**
160+
* Your TreeAncestor object will be instantiated and called as such:
161+
* TreeAncestor* obj = new TreeAncestor(n, parent);
162+
* int param_1 = obj->getKthAncestor(node,k);
163+
*/
164+
```
59165
166+
### **Go**
167+
168+
```go
169+
type TreeAncestor struct {
170+
p [][18]int
171+
}
172+
173+
func Constructor(n int, parent []int) TreeAncestor {
174+
p := make([][18]int, n)
175+
for i, fa := range parent {
176+
p[i][0] = fa
177+
for j := 1; j < 18; j++ {
178+
p[i][j] = -1
179+
}
180+
}
181+
for i := range p {
182+
for j := 1; j < 18; j++ {
183+
if p[i][j-1] == -1 {
184+
continue
185+
}
186+
p[i][j] = p[p[i][j-1]][j-1]
187+
}
188+
}
189+
return TreeAncestor{p}
190+
}
191+
192+
func (this *TreeAncestor) GetKthAncestor(node int, k int) int {
193+
for i := 17; i >= 0; i-- {
194+
if k>>i&1 == 1 {
195+
node = this.p[node][i]
196+
if node == -1 {
197+
break
198+
}
199+
}
200+
}
201+
return node
202+
}
203+
204+
/**
205+
* Your TreeAncestor object will be instantiated and called as such:
206+
* obj := Constructor(n, parent);
207+
* param_1 := obj.GetKthAncestor(node,k);
208+
*/
60209
```
61210

62211
### **...**
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class TreeAncestor {
2+
public:
3+
TreeAncestor(int n, vector<int>& parent) {
4+
p = vector<vector<int>>(n, vector<int>(18, -1));
5+
for (int i = 0; i < n; ++i) {
6+
p[i][0] = parent[i];
7+
}
8+
for (int i = 0; i < n; ++i) {
9+
for (int j = 1; j < 18; ++j) {
10+
if (p[i][j - 1] == -1) {
11+
continue;
12+
}
13+
p[i][j] = p[p[i][j - 1]][j - 1];
14+
}
15+
}
16+
}
17+
18+
int getKthAncestor(int node, int k) {
19+
for (int i = 17; ~i; --i) {
20+
if (k >> i & 1) {
21+
node = p[node][i];
22+
if (node == -1) {
23+
break;
24+
}
25+
}
26+
}
27+
return node;
28+
}
29+
30+
private:
31+
vector<vector<int>> p;
32+
};
33+
34+
/**
35+
* Your TreeAncestor object will be instantiated and called as such:
36+
* TreeAncestor* obj = new TreeAncestor(n, parent);
37+
* int param_1 = obj->getKthAncestor(node,k);
38+
*/

0 commit comments

Comments
 (0)