From f46fa3c73929e52c6c359f128201c9289fda7265 Mon Sep 17 00:00:00 2001 From: Manohar Reddy Poreddy <manoharporeddy@outlook.com> Date: Sat, 13 Jan 2024 21:21:00 +0530 Subject: [PATCH 1/8] Fix code, to pass test case https://leetcode.com/problems/kth-ancestor-of-a-tree-node/ ========= Wrong Answer Runtime: 78 ms Case 1 Case 2 Input ["TreeAncestor","getKthAncestor"] [[6,[-1,2,3,4,5,0]],[1,4]] Output [null,-1] Expected [null,5] --- .../1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md index 2a8ec0566bc51..d283942ba3f23 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md @@ -218,8 +218,8 @@ class TreeAncestor { for (let i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (let i = 0; i < n; ++i) { - for (let j = 1; j < 18; ++j) { + for (let j = 1; j < 18; ++j) { + for (let i = 0; i < n; ++i) { if (p[i][j - 1] === -1) { continue; } From 7cecd1ece625b80e1d93d40a4ebd03d2a3152f0f Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:09:52 +0800 Subject: [PATCH 2/8] Update README_EN.md --- .../README_EN.md | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md index d283942ba3f23..288d4edd06d72 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README_EN.md @@ -45,6 +45,28 @@ treeAncestor.getKthAncestor(6, 3); // returns -1 because there is no such ancest ## Solutions +**Solution 1: Dynamic Programming + Binary Lifting** + +The problem asks us to find the $k$-th ancestor node of a node $node$. If we solve it by brute force, we need to traverse upwards from $node$ for $k$ times, which has a time complexity of $O(k)$ and will obviously exceed the time limit. + +We can use dynamic programming combined with the idea of binary lifting to handle this. + +We define $p[i][j]$ as the $2^j$-th ancestor node of node $i$, i.e., the node reached by moving $2^j$ steps upwards from node $i$. Then we can get the state transition equation: + +$$ +p[i][j] = p[p[i][j-1]][j-1] +$$ + +That is, to find the $2^j$-th ancestor node of node $i$, we can first find the $2^{j-1}$-th ancestor node of node $i$, and then find the $2^{j-1}$-th ancestor node of this node. Therefore, we need to find the ancestor node of each node at a distance of $2^j$, until we reach the maximum height of the tree. + +For each query later, we can decompose $k$ into its binary representation, and then according to the positions of $1$ in the binary, we accumulate the queries upwards, and finally get the $k$-th ancestor node of node $node$. + +In terms of time complexity, the initialization is $O(n \times \log n)$, and the query is $O(\log n)$. The space complexity is $O(n \times \log n)$, where $n$ is the number of nodes in the tree. + +Similar problems: + +- [2836. Maximize Value of Function in a Ball Passing Game](/solution/2800-2899/2836.Maximize%20Value%20of%20Function%20in%20a%20Ball%20Passing%20Game/README_EN.md) + <!-- tabs:start --> ### **Python3** @@ -55,8 +77,8 @@ class TreeAncestor: self.p = [[-1] * 18 for _ in range(n)] for i, fa in enumerate(parent): self.p[i][0] = fa - for i in range(n): - for j in range(1, 18): + for j in range(1, 18): + for i in range(n): if self.p[i][j - 1] == -1: continue self.p[i][j] = self.p[self.p[i][j - 1]][j - 1] @@ -89,8 +111,8 @@ class TreeAncestor { for (int i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (int i = 0; i < n; ++i) { - for (int j = 1; j < 18; ++j) { + for (int j = 1; j < 18; ++j) { + for (int i = 0; i < n; ++i) { if (p[i][j - 1] == -1) { continue; } @@ -129,8 +151,8 @@ public: for (int i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (int i = 0; i < n; ++i) { - for (int j = 1; j < 18; ++j) { + for (int j = 1; j < 18; ++j) { + for (int i = 0; i < n; ++i) { if (p[i][j - 1] == -1) { continue; } @@ -177,8 +199,8 @@ func Constructor(n int, parent []int) TreeAncestor { p[i][j] = -1 } } - for i := range p { - for j := 1; j < 18; j++ { + for j := 1; j < 18; j++ { + for i := range p { if p[i][j-1] == -1 { continue } From 249176d68103b2fe80a689ce223dbbef13b21d35 Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:10:31 +0800 Subject: [PATCH 3/8] Update README.md --- .../README.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README.md b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README.md index c96a6c5e176e1..89fe1cf6b6c5d 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README.md +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/README.md @@ -89,8 +89,8 @@ class TreeAncestor: self.p = [[-1] * 18 for _ in range(n)] for i, fa in enumerate(parent): self.p[i][0] = fa - for i in range(n): - for j in range(1, 18): + for j in range(1, 18): + for i in range(n): if self.p[i][j - 1] == -1: continue self.p[i][j] = self.p[self.p[i][j - 1]][j - 1] @@ -125,8 +125,8 @@ class TreeAncestor { for (int i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (int i = 0; i < n; ++i) { - for (int j = 1; j < 18; ++j) { + for (int j = 1; j < 18; ++j) { + for (int i = 0; i < n; ++i) { if (p[i][j - 1] == -1) { continue; } @@ -165,8 +165,8 @@ public: for (int i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (int i = 0; i < n; ++i) { - for (int j = 1; j < 18; ++j) { + for (int j = 1; j < 18; ++j) { + for (int i = 0; i < n; ++i) { if (p[i][j - 1] == -1) { continue; } @@ -213,8 +213,8 @@ func Constructor(n int, parent []int) TreeAncestor { p[i][j] = -1 } } - for i := range p { - for j := 1; j < 18; j++ { + for j := 1; j < 18; j++ { + for i := range p { if p[i][j-1] == -1 { continue } @@ -246,6 +246,7 @@ func (this *TreeAncestor) GetKthAncestor(node int, k int) int { ### **TypeScript** ```ts +class TreeAncestor { class TreeAncestor { private p: number[][]; @@ -254,8 +255,8 @@ class TreeAncestor { for (let i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (let i = 0; i < n; ++i) { - for (let j = 1; j < 18; ++j) { + for (let j = 1; j < 18; ++j) { + for (let i = 0; i < n; ++i) { if (p[i][j - 1] === -1) { continue; } From 5729a1c9cfe6c13d3d450702590fc60b7f857e58 Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:11:08 +0800 Subject: [PATCH 4/8] Update Solution.py --- .../1400-1499/1483.Kth Ancestor of a Tree Node/Solution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.py b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.py index 708d6d0d0ca03..2f52c4dcc3b86 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.py +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.py @@ -3,8 +3,8 @@ def __init__(self, n: int, parent: List[int]): self.p = [[-1] * 18 for _ in range(n)] for i, fa in enumerate(parent): self.p[i][0] = fa - for i in range(n): - for j in range(1, 18): + for j in range(1, 18): + for i in range(n): if self.p[i][j - 1] == -1: continue self.p[i][j] = self.p[self.p[i][j - 1]][j - 1] From 5804e44391e82152fdaac7b8272ec45110f33375 Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:11:51 +0800 Subject: [PATCH 5/8] Update Solution.java --- .../1483.Kth Ancestor of a Tree Node/Solution.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.java b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.java index 059aa2e31e46b..fb9ccca670a93 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.java +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.java @@ -9,8 +9,8 @@ public TreeAncestor(int n, int[] parent) { for (int i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (int i = 0; i < n; ++i) { - for (int j = 1; j < 18; ++j) { + for (int j = 1; j < 18; ++j) { + for (int i = 0; i < n; ++i) { if (p[i][j - 1] == -1) { continue; } @@ -36,4 +36,4 @@ public int getKthAncestor(int node, int k) { * Your TreeAncestor object will be instantiated and called as such: * TreeAncestor obj = new TreeAncestor(n, parent); * int param_1 = obj.getKthAncestor(node,k); - */ \ No newline at end of file + */ From 17b604149fd87697f44a3870696bf8289aa0f415 Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:12:19 +0800 Subject: [PATCH 6/8] Update Solution.cpp --- .../1400-1499/1483.Kth Ancestor of a Tree Node/Solution.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.cpp b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.cpp index 1e742da970f3f..1197bbe436e55 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.cpp +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.cpp @@ -5,8 +5,8 @@ class TreeAncestor { for (int i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (int i = 0; i < n; ++i) { - for (int j = 1; j < 18; ++j) { + for (int j = 1; j < 18; ++j) { + for (int i = 0; i < n; ++i) { if (p[i][j - 1] == -1) { continue; } @@ -35,4 +35,4 @@ class TreeAncestor { * Your TreeAncestor object will be instantiated and called as such: * TreeAncestor* obj = new TreeAncestor(n, parent); * int param_1 = obj->getKthAncestor(node,k); - */ \ No newline at end of file + */ From e245fa3cc68965ed88d438a895cf7bdd5b4d2d62 Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:12:46 +0800 Subject: [PATCH 7/8] Update Solution.go --- .../1400-1499/1483.Kth Ancestor of a Tree Node/Solution.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.go b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.go index da0d002091622..04f04ede95880 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.go +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.go @@ -10,8 +10,8 @@ func Constructor(n int, parent []int) TreeAncestor { p[i][j] = -1 } } - for i := range p { - for j := 1; j < 18; j++ { + for j := 1; j < 18; j++ { + for i := range p { if p[i][j-1] == -1 { continue } @@ -37,4 +37,4 @@ func (this *TreeAncestor) GetKthAncestor(node int, k int) int { * Your TreeAncestor object will be instantiated and called as such: * obj := Constructor(n, parent); * param_1 := obj.GetKthAncestor(node,k); - */ \ No newline at end of file + */ From 1e9ed3fa87f59d5ef8048e7db0c15b36796662bc Mon Sep 17 00:00:00 2001 From: Libin YANG <contact@yanglibin.info> Date: Sun, 14 Jan 2024 09:13:11 +0800 Subject: [PATCH 8/8] Update Solution.ts --- .../1400-1499/1483.Kth Ancestor of a Tree Node/Solution.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.ts b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.ts index 2805876c5e50f..9f704a1ddccaa 100644 --- a/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.ts +++ b/solution/1400-1499/1483.Kth Ancestor of a Tree Node/Solution.ts @@ -6,8 +6,8 @@ class TreeAncestor { for (let i = 0; i < n; ++i) { p[i][0] = parent[i]; } - for (let i = 0; i < n; ++i) { - for (let j = 1; j < 18; ++j) { + for (let j = 1; j < 18; ++j) { + for (let i = 0; i < n; ++i) { if (p[i][j - 1] === -1) { continue; }