@@ -407,87 +407,188 @@ var getDirections = function (root, startValue, destValue) {
407407
408408<!-- solution:start -->
409409
410- #### 方法二:DFS
410+ ### 方法二:最近公共祖先 + DFS(优化)
411+
412+ 我们可以从 $\t extit{root}$ 出发,找到 $\t extit{startValue}$ 和 $\t extit{destValue}$ 的路径,记为 $\t extit{pathToStart}$ 和 $\t extit{pathToDest}$,然后去除 $\t extit{pathToStart}$ 和 $\t extit{pathToDest}$ 的最长公共前缀,此时 $\t extit{pathToStart}$ 的路径长度就是答案中 $\t extit{U}$ 的个数,而 $\t extit{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- */
432465class 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 ()
473+ && pathToStart .charAt (i) == pathToDest .charAt (i)) {
474+ ++ i;
443475 }
444- return new String (path, answerIdx, destLevel - answerIdx );
476+ return " U " . repeat ( pathToStart . length () - i) + pathToDest . substring (i );
445477 }
446478
447- private int findPaths (TreeNode node , int strtVal , int destVal , int level ) {
479+ private boolean dfs (TreeNode node , int x , StringBuilder path ) {
448480 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;
481+ return false ;
482+ }
483+ if (node .val == x) {
484+ return true ;
485+ }
486+ path .append (' L' );
487+ if (dfs (node .left , x, path)) {
488+ return true ;
489+ }
490+ path .setCharAt (path .length () - 1 , ' R' );
491+ if (dfs (node .right , x, path)) {
492+ return true ;
493+ }
494+ path .deleteCharAt (path .length () - 1 );
495+ return false ;
478496 }
479497}
480498` ` `
481499
482- <!-- tabs:end -->
500+ #### C++
483501
484- <!-- solution:end -->
502+ ` ` ` cpp
503+ /**
504+ * Definition for a binary tree node.
505+ * struct TreeNode {
506+ * int val;
507+ * TreeNode *left;
508+ * TreeNode *right;
509+ * TreeNode() : val(0), left(nullptr), right(nullptr) {}
510+ * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
511+ * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
512+ * };
513+ */
514+ class Solution {
515+ public:
516+ string getDirections (TreeNode * root , int startValue , int destValue ) {
517+ string pathToStart, pathToDest;
518+ dfs (root, startValue, pathToStart);
519+ dfs (root, destValue, pathToDest);
520+ int i = 0 ;
521+ while (i < pathToStart .size () && i < pathToDest .size () && pathToStart[i] == pathToDest[i]) {
522+ i++ ;
523+ }
524+ return string (pathToStart .size () - i, ' U' ) + pathToDest .substr (i);
525+ }
485526
486- <!-- solution:start -->
527+ private:
528+ bool dfs (TreeNode * node , int x , string & path ) {
529+ if (node == nullptr) {
530+ return false ;
531+ }
532+ if (node- > val == x) {
533+ return true ;
534+ }
535+ path .push_back (' L' );
536+ if (dfs (node- > left, x, path)) {
537+ return true ;
538+ }
539+ path .back () = ' R' ;
540+ if (dfs (node- > right, x, path)) {
541+ return true ;
542+ }
543+ path .pop_back ();
544+ return false ;
545+ }
546+ };
547+ ` ` `
487548
488- #### Solution 3: LCA + DFS (Optimized)
549+ #### Go
489550
490- <!-- tabs:start -->
551+ ` ` ` go
552+ /**
553+ * Definition for a binary tree node.
554+ * type TreeNode struct {
555+ * Val int
556+ * Left *TreeNode
557+ * Right *TreeNode
558+ * }
559+ */
560+ func getDirections (root * TreeNode, startValue int, destValue int) string {
561+ var dfs func (node * TreeNode, x int, path * []byte) bool
562+ dfs = func (node * TreeNode, x int, path * []byte) bool {
563+ if node == nil {
564+ return false
565+ }
566+ if node .Val == x {
567+ return true
568+ }
569+ * path = append (* path, ' L' )
570+ if dfs (node .Left , x , path ) {
571+ return true
572+ }
573+ (* path)[len (* path)- 1 ] = ' R'
574+ if dfs (node .Right , x , path ) {
575+ return true
576+ }
577+ * path = (* path)[: len (* path)- 1 ]
578+ return false
579+ }
580+
581+ pathToStart := []byte{}
582+ pathToDest := []byte{}
583+ dfs (root, startValue, & pathToStart)
584+ dfs (root, destValue, & pathToDest)
585+ i := 0
586+ for i < len (pathToStart) && i < len (pathToDest) && pathToStart[i] == pathToDest[i] {
587+ i++
588+ }
589+ return string (bytes .Repeat ([]byte{' U' }, len (pathToStart)- i)) + string (pathToDest[i: ])
590+ }
591+ ` ` `
491592
492593#### TypeScript
493594
@@ -505,35 +606,84 @@ class Solution {
505606 * }
506607 * }
507608 */
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 ;
512609
610+ function getDirections (root : TreeNode | null , startValue : number , destValue : number ): string {
611+ const dfs = (node: TreeNode | null , x: number, path: string[]): boolean => {
612+ if (node === null ) {
613+ return false ;
614+ }
615+ if (node .val === x) {
616+ return true ;
617+ }
513618 path .push (' L' );
514- if (dfs (node .left , x, path)) return true ;
515-
619+ if (dfs (node .left , x, path)) {
620+ return true ;
621+ }
516622 path[path .length - 1 ] = ' R' ;
517- if (dfs (node .right , x, path)) return true ;
623+ if (dfs (node .right , x, path)) {
624+ return true ;
625+ }
518626 path .pop ();
519-
520627 return false ;
521628 };
629+ const pathToStart: string [] = [];
630+ const pathToDest: string [] = [];
631+ dfs (root, startValue, pathToStart);
632+ dfs (root, destValue, pathToDest);
633+ let i = 0 ;
634+ while (pathToStart[i] === pathToDest[i]) {
635+ ++ i;
636+ }
637+ return ' U' .repeat (pathToStart .length - i) + pathToDest .slice (i).join (' ' );
638+ }
639+ ` ` `
522640
523- const startPath: string [] = [];
524- const destPath: string [] = [];
525- dfs (root, start, startPath);
526- dfs (root, dest, destPath);
641+ #### JavaScript
527642
643+ ` ` ` js
644+ /**
645+ * Definition for a binary tree node.
646+ * function TreeNode(val, left, right) {
647+ * this.val = (val===undefined ? 0 : val)
648+ * this.left = (left===undefined ? null : left)
649+ * this.right = (right===undefined ? null : right)
650+ * }
651+ */
652+ /**
653+ * @param {TreeNode} root
654+ * @param {number} startValue
655+ * @param {number} destValue
656+ * @return {string}
657+ */
658+ var getDirections = function (root , startValue , destValue ) {
659+ const dfs = (node , x , path ) => {
660+ if (node === null ) {
661+ return false ;
662+ }
663+ if (node .val === x) {
664+ return true ;
665+ }
666+ path .push (' L' );
667+ if (dfs (node .left , x, path)) {
668+ return true ;
669+ }
670+ path[path .length - 1 ] = ' R' ;
671+ if (dfs (node .right , x, path)) {
672+ return true ;
673+ }
674+ path .pop ();
675+ return false ;
676+ };
677+ const pathToStart = [];
678+ const pathToDest = [];
679+ dfs (root, startValue, pathToStart);
680+ dfs (root, destValue, pathToDest);
528681 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- }
682+ while (pathToStart[i] === pathToDest[i]) {
683+ ++ i;
684+ }
685+ return ' U' .repeat (pathToStart .length - i) + pathToDest .slice (i).join (' ' );
686+ };
537687` ` `
538688
539689<!-- tabs:end -->
0 commit comments