Skip to content

Commit 3c33eb5

Browse files
committed
feat: add solutions to lc problem: No.2096
No.2096.Step-By-Step Directions From a Binary Tree Node to Another
1 parent c5962ae commit 3c33eb5

File tree

10 files changed

+688
-298
lines changed

10 files changed

+688
-298
lines changed

solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README.md

Lines changed: 230 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -407,87 +407,187 @@ var getDirections = function (root, startValue, destValue) {
407407
408408
<!-- solution:start -->
409409
410-
#### 方法二:DFS
410+
### 方法二:最近公共祖先 + DFS(优化)
411+
412+
我们可以从 $\textit{root}$ 出发,找到 $\textit{startValue}$ 和 $\textit{destValue}$ 的路径,记为 $\textit{pathToStart}$ 和 $\textit{pathToDest}$,然后去除 $\textit{pathToStart}$ 和 $\textit{pathToDest}$ 的最长公共前缀,此时 $\textit{pathToStart}$ 的路径长度就是答案中 $\textit{U}$ 的个数,而 $\textit{pathToDest}$ 的路径就是答案中的路径,我们只需要将这两个路径拼接起来即可。
413+
414+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点数。
411415
412416
<!-- tabs:start -->
413417
418+
#### Python3
419+
420+
```python
421+
# Definition for a binary tree node.
422+
# class TreeNode:
423+
# def __init__(self, val=0, left=None, right=None):
424+
# self.val = val
425+
# self.left = left
426+
# self.right = right
427+
428+
429+
class Solution:
430+
def getDirections(
431+
self, root: Optional[TreeNode], startValue: int, destValue: int
432+
) -> str:
433+
def dfs(node: Optional[TreeNode], x: int, path: List[str]):
434+
if node is None:
435+
return False
436+
if node.val == x:
437+
return True
438+
path.append("L")
439+
if dfs(node.left, x, path):
440+
return True
441+
path[-1] = "R"
442+
if dfs(node.right, x, path):
443+
return True
444+
path.pop()
445+
return False
446+
447+
path_to_start = []
448+
path_to_dest = []
449+
450+
dfs(root, startValue, path_to_start)
451+
dfs(root, destValue, path_to_dest)
452+
i = 0
453+
while (
454+
i < len(path_to_start)
455+
and i < len(path_to_dest)
456+
and path_to_start[i] == path_to_dest[i]
457+
):
458+
i += 1
459+
return "U" * (len(path_to_start) - i) + "".join(path_to_dest[i:])
460+
```
461+
414462
#### Java
415463
416464
```java
417-
/**
418-
* Definition for a binary tree node.
419-
* public class TreeNode {
420-
* int val;
421-
* TreeNode left;
422-
* TreeNode right;
423-
* TreeNode() {}
424-
* TreeNode(int val) { this.val = val; }
425-
* TreeNode(int val, TreeNode left, TreeNode right) {
426-
* this.val = val;
427-
* this.left = left;
428-
* this.right = right;
429-
* }
430-
* }
431-
*/
432465
class Solution {
433-
static byte[] path = new byte[200_001];
434-
int strtLevel = -1;
435-
int destLevel = -1;
436-
int comnLevel = -1;
437-
438466
public String getDirections(TreeNode root, int startValue, int destValue) {
439-
findPaths(root, startValue, destValue, 100_000);
440-
int answerIdx = comnLevel;
441-
for (int i = strtLevel; i > comnLevel; i--) {
442-
path[--answerIdx] = 'U';
467+
StringBuilder pathToStart = new StringBuilder();
468+
StringBuilder pathToDest = new StringBuilder();
469+
dfs(root, startValue, pathToStart);
470+
dfs(root, destValue, pathToDest);
471+
int i = 0;
472+
while (i < pathToStart.length() && i < pathToDest.length() && pathToStart.charAt(i) == pathToDest.charAt(i)) {
473+
++i;
443474
}
444-
return new String(path, answerIdx, destLevel - answerIdx);
475+
return "U".repeat(pathToStart.length() - i) + pathToDest.substring(i);
445476
}
446477

447-
private int findPaths(TreeNode node, int strtVal, int destVal, int level) {
478+
private boolean dfs(TreeNode node, int x, StringBuilder path) {
448479
if (node == null) {
449-
return 0;
450-
}
451-
int result = 0;
452-
if (node.val == strtVal) {
453-
strtLevel = level;
454-
result = 1;
455-
} else if (node.val == destVal) {
456-
destLevel = level;
457-
result = 1;
458-
}
459-
int leftFound = 0;
460-
int rightFound = 0;
461-
if (comnLevel < 0) {
462-
if (destLevel < 0) {
463-
path[level] = 'L';
464-
}
465-
leftFound = findPaths(node.left, strtVal, destVal, level + 1);
466-
rightFound = 0;
467-
if (comnLevel < 0) {
468-
if (destLevel < 0) {
469-
path[level] = 'R';
470-
}
471-
rightFound = findPaths(node.right, strtVal, destVal, level + 1);
472-
}
473-
}
474-
if (comnLevel < 0 && leftFound + rightFound + result == 2) {
475-
comnLevel = level;
476-
}
477-
return result | leftFound | rightFound;
480+
return false;
481+
}
482+
if (node.val == x) {
483+
return true;
484+
}
485+
path.append('L');
486+
if (dfs(node.left, x, path)) {
487+
return true;
488+
}
489+
path.setCharAt(path.length() - 1, 'R');
490+
if (dfs(node.right, x, path)) {
491+
return true;
492+
}
493+
path.deleteCharAt(path.length() - 1);
494+
return false;
478495
}
479496
}
480497
```
481498
482-
<!-- tabs:end -->
499+
#### C++
483500
484-
<!-- solution:end -->
501+
```cpp
502+
/**
503+
* Definition for a binary tree node.
504+
* struct TreeNode {
505+
* int val;
506+
* TreeNode *left;
507+
* TreeNode *right;
508+
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
509+
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
510+
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
511+
* };
512+
*/
513+
class Solution {
514+
public:
515+
string getDirections(TreeNode* root, int startValue, int destValue) {
516+
string pathToStart, pathToDest;
517+
dfs(root, startValue, pathToStart);
518+
dfs(root, destValue, pathToDest);
519+
int i = 0;
520+
while (i < pathToStart.size() && i < pathToDest.size() && pathToStart[i] == pathToDest[i]) {
521+
i++;
522+
}
523+
return string(pathToStart.size() - i, 'U') + pathToDest.substr(i);
524+
}
485525

486-
<!-- solution:start -->
526+
private:
527+
bool dfs(TreeNode* node, int x, string& path) {
528+
if (node == nullptr) {
529+
return false;
530+
}
531+
if (node->val == x) {
532+
return true;
533+
}
534+
path.push_back('L');
535+
if (dfs(node->left, x, path)) {
536+
return true;
537+
}
538+
path.back() = 'R';
539+
if (dfs(node->right, x, path)) {
540+
return true;
541+
}
542+
path.pop_back();
543+
return false;
544+
}
545+
};
546+
```
487547
488-
#### Solution 3: LCA + DFS (Optimized)
548+
#### Go
489549
490-
<!-- tabs:start -->
550+
```go
551+
/**
552+
* Definition for a binary tree node.
553+
* type TreeNode struct {
554+
* Val int
555+
* Left *TreeNode
556+
* Right *TreeNode
557+
* }
558+
*/
559+
func getDirections(root *TreeNode, startValue int, destValue int) string {
560+
var dfs func(node *TreeNode, x int, path *[]byte) bool
561+
dfs = func(node *TreeNode, x int, path *[]byte) bool {
562+
if node == nil {
563+
return false
564+
}
565+
if node.Val == x {
566+
return true
567+
}
568+
*path = append(*path, 'L')
569+
if dfs(node.Left, x, path) {
570+
return true
571+
}
572+
(*path)[len(*path)-1] = 'R'
573+
if dfs(node.Right, x, path) {
574+
return true
575+
}
576+
*path = (*path)[:len(*path)-1]
577+
return false
578+
}
579+
580+
pathToStart := []byte{}
581+
pathToDest := []byte{}
582+
dfs(root, startValue, &pathToStart)
583+
dfs(root, destValue, &pathToDest)
584+
i := 0
585+
for i < len(pathToStart) && i < len(pathToDest) && pathToStart[i] == pathToDest[i] {
586+
i++
587+
}
588+
return string(bytes.Repeat([]byte{'U'}, len(pathToStart)-i)) + string(pathToDest[i:])
589+
}
590+
```
491591
492592
#### TypeScript
493593
@@ -505,35 +605,84 @@ class Solution {
505605
* }
506606
* }
507607
*/
508-
export function getDirections(root: TreeNode | null, start: number, dest: number): string {
509-
const dfs = (node: TreeNode | null, x: number, path: string[] = []): boolean => {
510-
if (!node) return false;
511-
if (node.val === x) return true;
512608

609+
function getDirections(root: TreeNode | null, startValue: number, destValue: number): string {
610+
const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => {
611+
if (node === null) {
612+
return false;
613+
}
614+
if (node.val === x) {
615+
return true;
616+
}
513617
path.push('L');
514-
if (dfs(node.left, x, path)) return true;
515-
618+
if (dfs(node.left, x, path)) {
619+
return true;
620+
}
516621
path[path.length - 1] = 'R';
517-
if (dfs(node.right, x, path)) return true;
622+
if (dfs(node.right, x, path)) {
623+
return true;
624+
}
518625
path.pop();
519-
520626
return false;
521627
};
628+
const pathToStart: string[] = [];
629+
const pathToDest: string[] = [];
630+
dfs(root, startValue, pathToStart);
631+
dfs(root, destValue, pathToDest);
632+
let i = 0;
633+
while (pathToStart[i] === pathToDest[i]) {
634+
++i;
635+
}
636+
return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join('');
637+
}
638+
```
522639
523-
const startPath: string[] = [];
524-
const destPath: string[] = [];
525-
dfs(root, start, startPath);
526-
dfs(root, dest, destPath);
640+
#### JavaScript
527641
642+
```js
643+
/**
644+
* Definition for a binary tree node.
645+
* function TreeNode(val, left, right) {
646+
* this.val = (val===undefined ? 0 : val)
647+
* this.left = (left===undefined ? null : left)
648+
* this.right = (right===undefined ? null : right)
649+
* }
650+
*/
651+
/**
652+
* @param {TreeNode} root
653+
* @param {number} startValue
654+
* @param {number} destValue
655+
* @return {string}
656+
*/
657+
var getDirections = function (root, startValue, destValue) {
658+
const dfs = (node, x, path) => {
659+
if (node === null) {
660+
return false;
661+
}
662+
if (node.val === x) {
663+
return true;
664+
}
665+
path.push('L');
666+
if (dfs(node.left, x, path)) {
667+
return true;
668+
}
669+
path[path.length - 1] = 'R';
670+
if (dfs(node.right, x, path)) {
671+
return true;
672+
}
673+
path.pop();
674+
return false;
675+
};
676+
const pathToStart = [];
677+
const pathToDest = [];
678+
dfs(root, startValue, pathToStart);
679+
dfs(root, destValue, pathToDest);
528680
let i = 0;
529-
while (startPath[i] === destPath[i]) i++;
530-
531-
return (
532-
Array(startPath.length - i)
533-
.fill('U')
534-
.join('') + destPath.slice(i).join('')
535-
);
536-
}
681+
while (pathToStart[i] === pathToDest[i]) {
682+
++i;
683+
}
684+
return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join('');
685+
};
537686
```
538687
539688
<!-- tabs:end -->

0 commit comments

Comments
 (0)