You are given the root of a binary tree with n nodes. Each node is uniquely assigned a value from 1 to n. You are also given an integer startValue representing the value of the start node s, and a different integer destValue representing the value of the destination node t.
Find the shortest path starting from node s and ending at node t. Generate step-by-step directions of such path as a string consisting of only the uppercase letters 'L', 'R', and 'U'. Each letter indicates a specific direction:
'L' means to go from a node to its left child node.
'R' means to go from a node to its right child node.
'U' means to go from a node to its parent node.
Return the step-by-step directions of the shortest path from node s to nodet.
Input: root = [2,1], startValue = 2, destValue = 1
Output: "L"
Explanation: The shortest path is: 2 → 1.
Constraints:
The number of nodes in the tree is n.
2 <= n <= 105
1 <= Node.val <= n
All the values in the tree are unique.
1 <= startValue, destValue <= n
startValue != destValue
Solutions
Solution 1: Lowest Common Ancestor + DFS
We can first find the lowest common ancestor of nodes \(\textit{startValue}\) and \(\textit{destValue}\), denoted as \(\textit{node}\). Then, starting from \(\textit{node}\), we find the paths to \(\textit{startValue}\) and \(\textit{destValue}\) respectively. The path from \(\textit{startValue}\) to \(\textit{node}\) will consist of a number of \(\textit{U}\)s, and the path from \(\textit{node}\) to \(\textit{destValue}\) will be the \(\textit{path}\). Finally, we concatenate these two paths.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the number of nodes in the binary tree.
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcgetDirections(root*TreeNode,startValueint,destValueint)string{varlcafunc(node*TreeNode,p,qint)*TreeNodelca=func(node*TreeNode,p,qint)*TreeNode{ifnode==nil||node.Val==p||node.Val==q{returnnode}left:=lca(node.Left,p,q)right:=lca(node.Right,p,q)ifleft!=nil&&right!=nil{returnnode}ifleft!=nil{returnleft}returnright}vardfsfunc(node*TreeNode,xint,path*[]byte)booldfs=func(node*TreeNode,xint,path*[]byte)bool{ifnode==nil{returnfalse}ifnode.Val==x{returntrue}*path=append(*path,'L')ifdfs(node.Left,x,path){returntrue}(*path)[len(*path)-1]='R'ifdfs(node.Right,x,path){returntrue}*path=(*path)[:len(*path)-1]returnfalse}node:=lca(root,startValue,destValue)pathToStart:=[]byte{}pathToDest:=[]byte{}dfs(node,startValue,&pathToStart)dfs(node,destValue,&pathToDest)returnstring(bytes.Repeat([]byte{'U'},len(pathToStart)))+string(pathToDest)}
Solution 2: Lowest Common Ancestor + DFS (Optimized)
We can start from \(\textit{root}\), find the paths to \(\textit{startValue}\) and \(\textit{destValue}\), denoted as \(\textit{pathToStart}\) and \(\textit{pathToDest}\), respectively. Then, remove the longest common prefix of \(\textit{pathToStart}\) and \(\textit{pathToDest}\). At this point, the length of \(\textit{pathToStart}\) is the number of \(\textit{U}\)s in the answer, and the path of \(\textit{pathToDest}\) is the path in the answer. We just need to concatenate these two paths.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the number of nodes in the binary tree.
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcgetDirections(root*TreeNode,startValueint,destValueint)string{vardfsfunc(node*TreeNode,xint,path*[]byte)booldfs=func(node*TreeNode,xint,path*[]byte)bool{ifnode==nil{returnfalse}ifnode.Val==x{returntrue}*path=append(*path,'L')ifdfs(node.Left,x,path){returntrue}(*path)[len(*path)-1]='R'ifdfs(node.Right,x,path){returntrue}*path=(*path)[:len(*path)-1]returnfalse}pathToStart:=[]byte{}pathToDest:=[]byte{}dfs(root,startValue,&pathToStart)dfs(root,destValue,&pathToDest)i:=0fori<len(pathToStart)&&i<len(pathToDest)&&pathToStart[i]==pathToDest[i]{i++}returnstring(bytes.Repeat([]byte{'U'},len(pathToStart)-i))+string(pathToDest[i:])}