diff --git a/solution/0800-0899/0864.Shortest Path to Get All Keys/README.md b/solution/0800-0899/0864.Shortest Path to Get All Keys/README.md index 765253be9c12a..5c6f89045c284 100644 --- a/solution/0800-0899/0864.Shortest Path to Get All Keys/README.md +++ b/solution/0800-0899/0864.Shortest Path to Get All Keys/README.md @@ -98,13 +98,13 @@ tags: f d c b ``` -我们定义一个队列 $q$ 来存储当前位置以及当前拥有的钥匙的状态,即 $(i, j, state)$,其中 $(i, j)$ 表示当前位置,$state$ 表示当前拥有的钥匙的状态,即 $state$ 的第 $i$ 位为 $1$ 表示当前拥有第 $i$ 把钥匙,否则表示当前没有第 $i$ 把钥匙。 +我们定义一个队列 $q$ 来存储当前位置以及当前拥有的钥匙的状态,即 $(i, j, \textit{state})$,其中 $(i, j)$ 表示当前位置,$\textit{state}$ 表示当前拥有的钥匙的状态,即 $\textit{state}$ 的第 $i$ 位为 $1$ 表示当前拥有第 $i$ 把钥匙,否则表示当前没有第 $i$ 把钥匙。 -另外,定义哈希表或数组 $vis$ 记录当前位置以及当前拥有的钥匙的状态是否已经被访问过,如果访问过,则不需要再次访问。$vis[i][j][state]$ 表示当前位置为 $(i, j)$,当前拥有的钥匙的状态为 $state$ 时,是否已经被访问过。 +另外,定义哈希表或数组 $vis$ 记录当前位置以及当前拥有的钥匙的状态是否已经被访问过,如果访问过,则不需要再次访问。$vis[i][j][\textit{state}]$ 表示当前位置为 $(i, j)$,当前拥有的钥匙的状态为 $state$ 时,是否已经被访问过。 我们从起点 $(si, sj)$ 出发,将其加入队列 $q$,并将 $vis[si][sj][0]$ 置为 $true$,表示起点位置以及拥有的钥匙的状态为 $0$ 时已经被访问过。 -在广度优先搜索的过程中,我们每次从队首取出一个位置 $(i, j, state)$,并判断当前位置是否为终点,即当前位置是否拥有所有的钥匙,即 $state$ 的二进制表示中的 $1$ 的个数是否为 $k$。如果是,将当前步数作为答案返回。 +在广度优先搜索的过程中,我们每次从队首取出一个位置 $(i, j, \textit{state})$,并判断当前位置是否为终点,即当前位置是否拥有所有的钥匙,即 $state$ 的二进制表示中的 $1$ 的个数是否为 $k$。如果是,将当前步数作为答案返回。 否则,我们从当前位置出发,往上下左右四个方向走,如果可以走到下一个位置 $(x, y)$,则将 $(x, y, nxt)$ 加入队列 $q$,其中 $nxt$ 表示下一个位置的钥匙的状态。 diff --git a/solution/0800-0899/0864.Shortest Path to Get All Keys/README_EN.md b/solution/0800-0899/0864.Shortest Path to Get All Keys/README_EN.md index d7e32a882c4ef..7f00dc75cb90e 100644 --- a/solution/0800-0899/0864.Shortest Path to Get All Keys/README_EN.md +++ b/solution/0800-0899/0864.Shortest Path to Get All Keys/README_EN.md @@ -80,7 +80,37 @@ tags: -### Solution 1 +### Solution 1: State Compression + BFS + +According to the problem description, we need to start from the initial position, move in four directions (up, down, left, right), collect all keys, and finally return the minimum number of moves required to collect all keys. If it is not possible to collect all keys, return $-1$. + +First, we traverse the 2D grid to find the starting position $(si, sj)$ and count the number of keys $k$. + +Then, we can use Breadth-First Search (BFS) to solve this problem. Since the number of keys ranges from $1$ to $6$, we can use a binary number to represent the state of the keys, where the $i$-th bit being $1$ indicates that the $i$-th key has been collected, and $0$ indicates that the $i$-th key has not been collected. + +For example, in the following case, there are $4$ bits set to $1$, indicating that keys `'b', 'c', 'd', 'f'` have been collected. + +``` +1 0 1 1 1 0 +^ ^ ^ ^ +f d c b +``` + +We define a queue $q$ to store the current position and the state of the collected keys, i.e., $(i, j, \textit{state})$, where $(i, j)$ represents the current position, and $\textit{state}$ represents the state of the collected keys. The $i$-th bit of $\textit{state}$ being $1$ indicates that the $i$-th key has been collected; otherwise, it indicates that the $i$-th key has not been collected. + +Additionally, we define a hash table or array $vis$ to record whether the current position and the state of the collected keys have been visited. If visited, there is no need to visit again. $vis[i][j][\textit{state}]$ indicates whether the position $(i, j)$ and the state of the collected keys $state$ have been visited. + +We start from the initial position $(si, sj)$, add it to the queue $q$, and set $vis[si][sj][0]$ to $true$, indicating that the initial position and the state of the collected keys $0$ have been visited. + +During the BFS process, we take out a position $(i, j, \textit{state})$ from the front of the queue and check whether the current position is the endpoint, i.e., whether the current position has collected all keys, which means the number of $1$s in the binary representation of $state$ is $k$. If so, we return the current number of steps as the answer. + +Otherwise, we move from the current position in four directions (up, down, left, right). If we can move to the next position $(x, y)$, we add $(x, y, nxt)$ to the queue $q$, where $nxt$ represents the state of the keys at the next position. + +Here, $(x, y)$ must first be within the grid range, i.e., $0 \leq x < m$ and $0 \leq y < n$. Secondly, if the position $(x, y)$ is a wall, i.e., `grid[x][y] == '#'`, or the position $(x, y)$ is a lock but we do not have the corresponding key, i.e., `grid[x][y] >= 'A' && grid[x][y] <= 'F' && (state >> (grid[x][y] - 'A') & 1) == 0)`, then we cannot move to the position $(x, y)`. Otherwise, we can move to the position $(x, y)`. + +If the search ends and we have not collected all keys, return $-1$. + +The time complexity is $O(m \times n \times 2^k)$, and the space complexity is $O(m \times n \times 2^k)$. Here, $m$ and $n$ are the number of rows and columns of the grid, respectively, and $k$ is the number of keys. @@ -90,9 +120,9 @@ tags: class Solution: def shortestPathAllKeys(self, grid: List[str]) -> int: m, n = len(grid), len(grid[0]) - # 找起点 (si, sj) + # Find the starting point (si, sj) si, sj = next((i, j) for i in range(m) for j in range(n) if grid[i][j] == '@') - # 统计钥匙数量 + # Count the number of keys k = sum(v.islower() for row in grid for v in row) dirs = (-1, 0, 1, 0, -1) q = deque([(si, sj, 0)]) @@ -101,33 +131,33 @@ class Solution: while q: for _ in range(len(q)): i, j, state = q.popleft() - # 找到所有钥匙,返回当前步数 + # If all keys are found, return the current step count if state == (1 << k) - 1: return ans - # 往四个方向搜索 + # Search in the four directions for a, b in pairwise(dirs): x, y = i + a, j + b nxt = state - # 在边界范围内 + # Within boundary limits if 0 <= x < m and 0 <= y < n: c = grid[x][y] - # 是墙,或者是锁,但此时没有对应的钥匙,无法通过 + # It's a wall, or it's a lock but we don't have the key for it if ( c == '#' or c.isupper() and (state & (1 << (ord(c) - ord('A')))) == 0 ): continue - # 是钥匙 + # It's a key if c.islower(): - # 更新状态 + # Update the state nxt |= 1 << (ord(c) - ord('a')) - # 此状态未访问过,入队 + # If this state has not been visited, enqueue it if (x, y, nxt) not in vis: vis.add((x, y, nxt)) q.append((x, y, nxt)) - # 步数加一 + # Increment the step count ans += 1 return -1 ``` @@ -146,10 +176,10 @@ class Solution { for (int j = 0; j < n; ++j) { char c = grid[i].charAt(j); if (Character.isLowerCase(c)) { - // 累加钥匙数量 + // Count the number of keys ++k; } else if (c == '@') { - // 起点 + // Starting point si = i; sj = j; } @@ -164,28 +194,28 @@ class Solution { for (int t = q.size(); t > 0; --t) { var p = q.poll(); int i = p[0], j = p[1], state = p[2]; - // 找到所有钥匙,返回当前步数 + // If all keys are found, return the current step count if (state == (1 << k) - 1) { return ans; } - // 往四个方向搜索 + // Search in the four directions for (int h = 0; h < 4; ++h) { int x = i + dirs[h], y = j + dirs[h + 1]; - // 在边界范围内 + // Within boundary limits if (x >= 0 && x < m && y >= 0 && y < n) { char c = grid[x].charAt(y); - // 是墙,或者是锁,但此时没有对应的钥匙,无法通过 + // It's a wall, or it's a lock without the corresponding key if (c == '#' || (Character.isUpperCase(c) && ((state >> (c - 'A')) & 1) == 0)) { continue; } int nxt = state; - // 是钥匙 + // If it's a key if (Character.isLowerCase(c)) { - // 更新状态 + // Update the state nxt |= 1 << (c - 'a'); } - // 此状态未访问过,入队 + // If this state has not been visited, enqueue it if (!vis[x][y][nxt]) { vis[x][y][nxt] = true; q.offer(new int[] {x, y, nxt}); @@ -193,7 +223,7 @@ class Solution { } } } - // 步数加一 + // Increment the step count ++ans; } return -1; @@ -215,9 +245,9 @@ public: for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { char c = grid[i][j]; - // 累加钥匙数量 + // Count the number of keys if (islower(c)) ++k; - // 起点 + // Starting point else if (c == '@') si = i, sj = j; } @@ -230,20 +260,20 @@ public: for (int t = q.size(); t; --t) { auto [i, j, state] = q.front(); q.pop(); - // 找到所有钥匙,返回当前步数 + // If all keys are found, return the current step count if (state == (1 << k) - 1) return ans; - // 往四个方向搜索 + // Search in the four directions for (int h = 0; h < 4; ++h) { int x = i + dirs[h], y = j + dirs[h + 1]; - // 在边界范围内 + // Within boundary limits if (x >= 0 && x < m && y >= 0 && y < n) { char c = grid[x][y]; - // 是墙,或者是锁,但此时没有对应的钥匙,无法通过 + // It's a wall, or it's a lock without the corresponding key if (c == '#' || (isupper(c) && (state >> (c - 'A') & 1) == 0)) continue; int nxt = state; - // 是钥匙,更新状态 + // If it's a key, update the state if (islower(c)) nxt |= 1 << (c - 'a'); - // 此状态未访问过,入队 + // If this state has not been visited, enqueue it if (!vis[x][y][nxt]) { vis[x][y][nxt] = true; q.push({x, y, nxt}); @@ -251,7 +281,7 @@ public: } } } - // 步数加一 + // Increment the step count ++ans; } return -1; @@ -268,10 +298,10 @@ func shortestPathAllKeys(grid []string) int { for i, row := range grid { for j, c := range row { if c >= 'a' && c <= 'z' { - // 累加钥匙数量 + // Count the number of keys k++ } else if c == '@' { - // 起点 + // Starting point si, sj = i, j } } @@ -286,26 +316,26 @@ func shortestPathAllKeys(grid []string) int { p := q[0] q = q[1:] i, j, state := p.i, p.j, p.state - // 找到所有钥匙,返回当前步数 + // If all keys are found, return the current step count if state == 1<= 0 && x < m && y >= 0 && y < n { c := grid[x][y] - // 是墙,或者是锁,但此时没有对应的钥匙,无法通过 + // It's a wall, or it's a lock without the corresponding key if c == '#' || (c >= 'A' && c <= 'Z' && (state>>(c-'A')&1 == 0)) { continue } nxt := state - // 是钥匙,更新状态 + // If it's a key, update the state if c >= 'a' && c <= 'z' { nxt |= 1 << (c - 'a') } - // 此状态未访问过,入队 + // If this state has not been visited, enqueue it if !vis[tuple{x, y, nxt}] { vis[tuple{x, y, nxt}] = true q = append(q, tuple{x, y, nxt}) @@ -313,7 +343,7 @@ func shortestPathAllKeys(grid []string) int { } } } - // 步数加一 + // Increment the step count ans++ } return -1 diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README.md b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README.md index 2dabf1de147f5..400b4f45c2715 100644 --- a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README.md +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README.md @@ -77,7 +77,18 @@ tags: -### 方法一 +### 方法一:递归 + +我们设计一个函数 $\textit{dfs}(\textit{root})$,返回以 $\textit{root}$ 为根的子树中,包含所有最深节点的最小子树,以及以 $\textit{root}$ 为根的子树的深度。 + +函数 $\textit{dfs}(\textit{root})$ 的执行过程如下: + +- 如果 $\textit{root}$ 为空,返回 $\text{null}$ 和 $0$。 +- 否则,递归计算 $\textit{root}$ 的左子树和右子树的最小子树以及深度,分别为 $l$ 和 $l_d$ 以及 $r$ 和 $r_d$。如果 $l_d > r_d$,则以 $\textit{root}$ 的左孩子为根的子树中包含所有最深节点的最小子树就是 $l$,深度为 $l_d + 1$;如果 $l_d < r_d$,则以 $\textit{root}$ 的右孩子为根的子树中包含所有最深节点的最小子树就是 $r$,深度为 $r_d + 1$;如果 $l_d = r_d$,则 $\textit{root}$ 就是包含所有最深节点的最小子树,深度为 $l_d + 1$。 + +最后,返回 $\textit{dfs}(\textit{root})$ 的结果的第一个元素即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点个数。 @@ -91,17 +102,17 @@ tags: # self.left = left # self.right = right class Solution: - def subtreeWithAllDeepest(self, root: TreeNode) -> TreeNode: - def dfs(root): + def subtreeWithAllDeepest(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + def dfs(root: Optional[TreeNode]) -> Tuple[Optional[TreeNode], int]: if root is None: return None, 0 - l, d1 = dfs(root.left) - r, d2 = dfs(root.right) - if d1 > d2: - return l, d1 + 1 - if d1 < d2: - return r, d2 + 1 - return root, d1 + 1 + l, ld = dfs(root.left) + r, rd = dfs(root.right) + if ld > rd: + return l, ld + 1 + if ld < rd: + return r, rd + 1 + return root, ld + 1 return dfs(root)[0] ``` @@ -133,16 +144,16 @@ class Solution { if (root == null) { return new Pair<>(null, 0); } - Pair l = dfs(root.left); - Pair r = dfs(root.right); - int d1 = l.getValue(), d2 = r.getValue(); - if (d1 > d2) { - return new Pair<>(l.getKey(), d1 + 1); + var l = dfs(root.left); + var r = dfs(root.right); + int ld = l.getValue(), rd = r.getValue(); + if (ld > rd) { + return new Pair<>(l.getKey(), ld + 1); } - if (d1 < d2) { - return new Pair<>(r.getKey(), d2 + 1); + if (ld < rd) { + return new Pair<>(r.getKey(), rd + 1); } - return new Pair<>(root, d1 + 1); + return new Pair<>(root, ld + 1); } } ``` @@ -161,21 +172,25 @@ class Solution { * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ -using pti = pair; class Solution { public: TreeNode* subtreeWithAllDeepest(TreeNode* root) { - return dfs(root).first; - } - - pti dfs(TreeNode* root) { - if (!root) return {nullptr, 0}; - pti l = dfs(root->left); - pti r = dfs(root->right); - int d1 = l.second, d2 = r.second; - if (d1 > d2) return {l.first, d1 + 1}; - if (d1 < d2) return {r.first, d2 + 1}; - return {root, d1 + 1}; + using pti = pair; + auto dfs = [&](auto&& dfs, TreeNode* root) -> pti { + if (!root) { + return {nullptr, 0}; + } + auto [l, ld] = dfs(dfs, root->left); + auto [r, rd] = dfs(dfs, root->right); + if (ld > rd) { + return {l, ld + 1}; + } + if (ld < rd) { + return {r, rd + 1}; + } + return {root, ld + 1}; + }; + return dfs(dfs, root).first; } }; ``` @@ -191,28 +206,63 @@ public: * Right *TreeNode * } */ -type pair struct { - first *TreeNode - second int -} - func subtreeWithAllDeepest(root *TreeNode) *TreeNode { - var dfs func(root *TreeNode) pair + type pair struct { + node *TreeNode + depth int + } + var dfs func(*TreeNode) pair dfs = func(root *TreeNode) pair { if root == nil { return pair{nil, 0} } l, r := dfs(root.Left), dfs(root.Right) - d1, d2 := l.second, r.second - if d1 > d2 { - return pair{l.first, d1 + 1} + ld, rd := l.depth, r.depth + if ld > rd { + return pair{l.node, ld + 1} } - if d1 < d2 { - return pair{r.first, d2 + 1} + if ld < rd { + return pair{r.node, rd + 1} } - return pair{root, d1 + 1} + return pair{root, ld + 1} } - return dfs(root).first + return dfs(root).node +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function subtreeWithAllDeepest(root: TreeNode | null): TreeNode | null { + const dfs = (root: TreeNode | null): [TreeNode, number] => { + if (!root) { + return [null, 0]; + } + const [l, ld] = dfs(root.left); + const [r, rd] = dfs(root.right); + if (ld > rd) { + return [l, ld + 1]; + } + if (ld < rd) { + return [r, rd + 1]; + } + return [root, ld + 1]; + }; + return dfs(root)[0]; } ``` diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README_EN.md b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README_EN.md index 20905c011431c..3af2763735df6 100644 --- a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README_EN.md +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/README_EN.md @@ -73,7 +73,18 @@ Notice that nodes 5, 3 and 2 contain the deepest nodes in the tree but node 2 is -### Solution 1 +### Solution 1: Recursion + +We design a function $\textit{dfs}(\textit{root})$ that returns the smallest subtree containing all the deepest nodes in the subtree rooted at $\textit{root}$, as well as the depth of the subtree rooted at $\textit{root}$. + +The execution process of the function $\textit{dfs}(\textit{root})$ is as follows: + +- If $\textit{root}$ is null, return $\text{null}$ and $0$. +- Otherwise, recursively calculate the smallest subtree and depth of the left and right subtrees of $\textit{root}$, denoted as $l$ and $l_d$, and $r$ and $r_d$, respectively. If $l_d > r_d$, then the smallest subtree containing all the deepest nodes in the subtree rooted at the left child of $\textit{root}$ is $l$, with a depth of $l_d + 1$. If $l_d < r_d$, then the smallest subtree containing all the deepest nodes in the subtree rooted at the right child of $\textit{root}$ is $r$, with a depth of $r_d + 1$. If $l_d = r_d$, then $\textit{root}$ is the smallest subtree containing all the deepest nodes, with a depth of $l_d + 1$. + +Finally, return the first element of the result of $\textit{dfs}(\textit{root})$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -87,17 +98,17 @@ Notice that nodes 5, 3 and 2 contain the deepest nodes in the tree but node 2 is # self.left = left # self.right = right class Solution: - def subtreeWithAllDeepest(self, root: TreeNode) -> TreeNode: - def dfs(root): + def subtreeWithAllDeepest(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + def dfs(root: Optional[TreeNode]) -> Tuple[Optional[TreeNode], int]: if root is None: return None, 0 - l, d1 = dfs(root.left) - r, d2 = dfs(root.right) - if d1 > d2: - return l, d1 + 1 - if d1 < d2: - return r, d2 + 1 - return root, d1 + 1 + l, ld = dfs(root.left) + r, rd = dfs(root.right) + if ld > rd: + return l, ld + 1 + if ld < rd: + return r, rd + 1 + return root, ld + 1 return dfs(root)[0] ``` @@ -129,16 +140,16 @@ class Solution { if (root == null) { return new Pair<>(null, 0); } - Pair l = dfs(root.left); - Pair r = dfs(root.right); - int d1 = l.getValue(), d2 = r.getValue(); - if (d1 > d2) { - return new Pair<>(l.getKey(), d1 + 1); + var l = dfs(root.left); + var r = dfs(root.right); + int ld = l.getValue(), rd = r.getValue(); + if (ld > rd) { + return new Pair<>(l.getKey(), ld + 1); } - if (d1 < d2) { - return new Pair<>(r.getKey(), d2 + 1); + if (ld < rd) { + return new Pair<>(r.getKey(), rd + 1); } - return new Pair<>(root, d1 + 1); + return new Pair<>(root, ld + 1); } } ``` @@ -157,21 +168,25 @@ class Solution { * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ -using pti = pair; class Solution { public: TreeNode* subtreeWithAllDeepest(TreeNode* root) { - return dfs(root).first; - } - - pti dfs(TreeNode* root) { - if (!root) return {nullptr, 0}; - pti l = dfs(root->left); - pti r = dfs(root->right); - int d1 = l.second, d2 = r.second; - if (d1 > d2) return {l.first, d1 + 1}; - if (d1 < d2) return {r.first, d2 + 1}; - return {root, d1 + 1}; + using pti = pair; + auto dfs = [&](auto&& dfs, TreeNode* root) -> pti { + if (!root) { + return {nullptr, 0}; + } + auto [l, ld] = dfs(dfs, root->left); + auto [r, rd] = dfs(dfs, root->right); + if (ld > rd) { + return {l, ld + 1}; + } + if (ld < rd) { + return {r, rd + 1}; + } + return {root, ld + 1}; + }; + return dfs(dfs, root).first; } }; ``` @@ -187,28 +202,63 @@ public: * Right *TreeNode * } */ -type pair struct { - first *TreeNode - second int -} - func subtreeWithAllDeepest(root *TreeNode) *TreeNode { - var dfs func(root *TreeNode) pair + type pair struct { + node *TreeNode + depth int + } + var dfs func(*TreeNode) pair dfs = func(root *TreeNode) pair { if root == nil { return pair{nil, 0} } l, r := dfs(root.Left), dfs(root.Right) - d1, d2 := l.second, r.second - if d1 > d2 { - return pair{l.first, d1 + 1} + ld, rd := l.depth, r.depth + if ld > rd { + return pair{l.node, ld + 1} } - if d1 < d2 { - return pair{r.first, d2 + 1} + if ld < rd { + return pair{r.node, rd + 1} } - return pair{root, d1 + 1} + return pair{root, ld + 1} } - return dfs(root).first + return dfs(root).node +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function subtreeWithAllDeepest(root: TreeNode | null): TreeNode | null { + const dfs = (root: TreeNode | null): [TreeNode, number] => { + if (!root) { + return [null, 0]; + } + const [l, ld] = dfs(root.left); + const [r, rd] = dfs(root.right); + if (ld > rd) { + return [l, ld + 1]; + } + if (ld < rd) { + return [r, rd + 1]; + } + return [root, ld + 1]; + }; + return dfs(root)[0]; } ``` diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.cpp b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.cpp index ec35da83da5fa..c7a0066c01fcd 100644 --- a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.cpp +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.cpp @@ -9,20 +9,24 @@ * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ -using pti = pair; class Solution { public: TreeNode* subtreeWithAllDeepest(TreeNode* root) { - return dfs(root).first; + using pti = pair; + auto dfs = [&](auto&& dfs, TreeNode* root) -> pti { + if (!root) { + return {nullptr, 0}; + } + auto [l, ld] = dfs(dfs, root->left); + auto [r, rd] = dfs(dfs, root->right); + if (ld > rd) { + return {l, ld + 1}; + } + if (ld < rd) { + return {r, rd + 1}; + } + return {root, ld + 1}; + }; + return dfs(dfs, root).first; } - - pti dfs(TreeNode* root) { - if (!root) return {nullptr, 0}; - pti l = dfs(root->left); - pti r = dfs(root->right); - int d1 = l.second, d2 = r.second; - if (d1 > d2) return {l.first, d1 + 1}; - if (d1 < d2) return {r.first, d2 + 1}; - return {root, d1 + 1}; - } -}; \ No newline at end of file +}; diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.go b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.go index 4e7049fa5e5c8..38077a8dca34d 100644 --- a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.go +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.go @@ -6,26 +6,25 @@ * Right *TreeNode * } */ -type pair struct { - first *TreeNode - second int -} - func subtreeWithAllDeepest(root *TreeNode) *TreeNode { - var dfs func(root *TreeNode) pair + type pair struct { + node *TreeNode + depth int + } + var dfs func(*TreeNode) pair dfs = func(root *TreeNode) pair { if root == nil { return pair{nil, 0} } l, r := dfs(root.Left), dfs(root.Right) - d1, d2 := l.second, r.second - if d1 > d2 { - return pair{l.first, d1 + 1} + ld, rd := l.depth, r.depth + if ld > rd { + return pair{l.node, ld + 1} } - if d1 < d2 { - return pair{r.first, d2 + 1} + if ld < rd { + return pair{r.node, rd + 1} } - return pair{root, d1 + 1} + return pair{root, ld + 1} } - return dfs(root).first -} \ No newline at end of file + return dfs(root).node +} diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.java b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.java index 57b838e3f2a79..87cae36728482 100644 --- a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.java +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.java @@ -22,15 +22,15 @@ private Pair dfs(TreeNode root) { if (root == null) { return new Pair<>(null, 0); } - Pair l = dfs(root.left); - Pair r = dfs(root.right); - int d1 = l.getValue(), d2 = r.getValue(); - if (d1 > d2) { - return new Pair<>(l.getKey(), d1 + 1); + var l = dfs(root.left); + var r = dfs(root.right); + int ld = l.getValue(), rd = r.getValue(); + if (ld > rd) { + return new Pair<>(l.getKey(), ld + 1); } - if (d1 < d2) { - return new Pair<>(r.getKey(), d2 + 1); + if (ld < rd) { + return new Pair<>(r.getKey(), rd + 1); } - return new Pair<>(root, d1 + 1); + return new Pair<>(root, ld + 1); } -} \ No newline at end of file +} diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.py b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.py index 6df9e22d305e1..f1540fb613ea5 100644 --- a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.py +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.py @@ -5,16 +5,16 @@ # self.left = left # self.right = right class Solution: - def subtreeWithAllDeepest(self, root: TreeNode) -> TreeNode: - def dfs(root): + def subtreeWithAllDeepest(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + def dfs(root: Optional[TreeNode]) -> Tuple[Optional[TreeNode], int]: if root is None: return None, 0 - l, d1 = dfs(root.left) - r, d2 = dfs(root.right) - if d1 > d2: - return l, d1 + 1 - if d1 < d2: - return r, d2 + 1 - return root, d1 + 1 + l, ld = dfs(root.left) + r, rd = dfs(root.right) + if ld > rd: + return l, ld + 1 + if ld < rd: + return r, rd + 1 + return root, ld + 1 return dfs(root)[0] diff --git a/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.ts b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.ts new file mode 100644 index 0000000000000..9806c84cefba0 --- /dev/null +++ b/solution/0800-0899/0865.Smallest Subtree with all the Deepest Nodes/Solution.ts @@ -0,0 +1,31 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function subtreeWithAllDeepest(root: TreeNode | null): TreeNode | null { + const dfs = (root: TreeNode | null): [TreeNode, number] => { + if (!root) { + return [null, 0]; + } + const [l, ld] = dfs(root.left); + const [r, rd] = dfs(root.right); + if (ld > rd) { + return [l, ld + 1]; + } + if (ld < rd) { + return [r, rd + 1]; + } + return [root, ld + 1]; + }; + return dfs(root)[0]; +}