-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2096-StepByStepDirectionsFromABinaryTreeNodeToAnother.go
More file actions
213 lines (197 loc) · 6.71 KB
/
2096-StepByStepDirectionsFromABinaryTreeNodeToAnother.go
File metadata and controls
213 lines (197 loc) · 6.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package main
// 2096. Step-By-Step Directions From a Binary Tree Node to Another
// 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 node t.
// Example 1:
// <img src="https://assets.leetcode.com/uploads/2021/11/15/eg1.png" />
// Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6
// Output: "UURL"
// Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6.
// Example 2:
// <img src="https://assets.leetcode.com/uploads/2021/11/15/eg2.png" />
// 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 <= 10^5
// 1 <= Node.val <= n
// All the values in the tree are unique.
// 1 <= startValue, destValue <= n
// startValue != destValue
import "fmt"
import "strings"
// Definition for a binary tree node.
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
// dfs + bfs
func getDirections(root *TreeNode, startValue, destValue int) string {
queue, parents := []*TreeNode{nil}, map[*TreeNode]*TreeNode{}
var dfs func(node, pa *TreeNode)
dfs = func(node, pa *TreeNode) {
if node == nil { return }
parents[node] = pa
if node.Val == startValue {
queue[0] = node // 只有一个起点
}
dfs(node.Left, node)
dfs(node.Right, node)
}
dfs(root, nil)
res, vis := []byte{}, map[*TreeNode]bool{nil: true, queue[0]: true}
type pair struct {
from *TreeNode
dir byte
}
from := map[*TreeNode]pair{}
for len(queue) > 0 {
node := queue[0]
queue = queue[1:]
if node.Val == destValue {
for ; from[node].from != nil; node = from[node].from {
res = append(res, from[node].dir)
}
break
}
if !vis[node.Left] {
vis[node.Left] = true
from[node.Left] = pair{node, 'L'}
queue = append(queue, node.Left)
}
if !vis[node.Right] {
vis[node.Right] = true
from[node.Right] = pair{node, 'R'}
queue = append(queue, node.Right)
}
if !vis[parents[node]] {
vis[parents[node]] = true
from[parents[node]] = pair{node, 'U'}
queue = append(queue, parents[node])
}
}
for i, n := 0, len(res); i < n/2; i++ {
res[i], res[n-1-i] = res[n-1-i], res[i]
}
return string(res)
}
// 最近公共祖先
func getDirections1(root *TreeNode, startValue, destValue int) string {
path := []byte{}
var dfs func(*TreeNode, int) bool
dfs = func(node *TreeNode, target int) bool {
if node == nil { return false }
if node.Val == target { return true }
path = append(path, 'L')
if dfs(node.Left, target) { return true }
path[len(path)-1] = 'R'
if dfs(node.Right, target) { return true }
path = path[:len(path)-1]
return false
}
dfs(root, startValue)
pathToStart := path
path = nil
dfs(root, destValue)
pathToDest := path
for len(pathToStart) > 0 && len(pathToDest) > 0 && pathToStart[0] == pathToDest[0] {
pathToStart = pathToStart[1:] // 去掉前缀相同的部分
pathToDest = pathToDest[1:]
}
return strings.Repeat("U", len(pathToStart)) + string(pathToDest)
}
func getDirections2(root *TreeNode, startValue int, destValue int) string {
var findTarget func(root *TreeNode, targetValue int, path *[]byte) bool
findTarget = func(root *TreeNode, targetValue int, path *[]byte) bool {
if root.Val == targetValue {
return true
}
if root.Left != nil && findTarget(root.Left, targetValue, path) {
*path = append(*path, 'L')
return true
}
if root.Right != nil && findTarget(root.Right, targetValue, path) {
*path = append(*path, 'R')
return true
}
return false
}
reverse := func (path []byte) {
left, right := 0, len(path)-1
for left < right {
path[left], path[right] = path[right], path[left]
left++
right--
}
}
replace := func(path []byte) {
for i := 0; i < len(path); i++ {
path[i] = 'U'
}
}
min := func (x, y int) int { if x < y { return x; }; return y; }
sPath, dPath := make([]byte, 0), make([]byte, 0)
findTarget(root, startValue, &sPath)
findTarget(root, destValue, &dPath)
size, i := min(len(sPath), len(dPath)), 0
for i < size {
if sPath[len(sPath)-1-i] == dPath[len(dPath)-1-i] {
i++
} else {
break
}
}
sPath = sPath[:len(sPath)-i]
replace(sPath)
dPath = dPath[:len(dPath)-i]
reverse(dPath)
sPath = append(sPath, dPath...)
return string(sPath)
}
func main() {
// Example 1:
// <img src="https://assets.leetcode.com/uploads/2021/11/15/eg1.png" />
// Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6
// Output: "UURL"
// Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6.
tree1 := &TreeNode {
5,
&TreeNode { 1, &TreeNode { 3, nil, nil }, nil },
&TreeNode { 2, &TreeNode { 6, nil, nil }, &TreeNode { 4, nil, nil } },
}
fmt.Println(getDirections(tree1,3, 6)) // "UURL"
// Example 2:
// <img src="https://assets.leetcode.com/uploads/2021/11/15/eg2.png" />
// Input: root = [2,1], startValue = 2, destValue = 1
// Output: "L"
// Explanation: The shortest path is: 2 → 1.
tree2 := &TreeNode {
1,
&TreeNode { 2, nil, nil },
nil,
}
fmt.Println(getDirections(tree2,2, 1)) // "L"
fmt.Println(getDirections1(tree1,3, 6)) // "UURL"
fmt.Println(getDirections1(tree2,2, 1)) // "L"
fmt.Println(getDirections2(tree1,3, 6)) // "UURL"
fmt.Println(getDirections2(tree2,2, 1)) // "L"
}