2096、从二叉树一个节点到另一个节点每一步方向
给你一棵 二叉树 的根节点 root ,这棵二叉树总共有 n 个节点。每个节点的值为 1 到 n 中的一个整数,且互不相同。给你一个整数 startValue ,表示起点节点 s 的值,和另一个不同的整数 destValue ,表示终点节点 t 的值。
请找到从节点 s 到节点 t 的 最短路径 ,并以字符串的形式返回每一步的方向。每一步用 大写 字母 ‘L’ ,‘R’ 和 ‘U’ 分别表示一种方向:
- ‘L’ 表示从一个节点前往它的 左孩子 节点。
- ‘R’ 表示从一个节点前往它的 右孩子 节点。
- ‘U’ 表示从一个节点前往它的 父 节点。
请你返回从 s 到 t 最短路径 每一步的方向。
示例1:
输入:root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6
输出:"UURL"
解释:最短路径为:3 → 1 → 5 → 2 → 6 。
示例2:
输入:root = [2,1], startValue = 2, destValue = 1
输出:"L"
解释:最短路径为:2 → 1 。
思路:
可以先找到起点节点和终点节点路径,如果起点和终点路径有重复的路径,那么说明是祖父节点,找到起始路径和终点路径不同的部分,然后将起始路径改成U即可
class Solution:
def reversePath(self, path):
return 'U'*len(path)
def getDirections(self, root: Optional[TreeNode], startValue: int, destValue: int) -> str:
self.startPath = ""
self.destPath = ""
# 通过深度优先遍历获取起始路径和终点路径
def dfs(root, prefix):
if not root: return
if root.val == startValue:
self.startPath = prefix
if root.val == destValue:
self.destPath = prefix
dfs(root.left, prefix + 'L')
dfs(root.right, prefix + 'R')
dfs(root, "")
sn, dn = len(self.startPath), len(self.destPath)
# 找到起始路径和终点路径不同的下标
# 更新后的起始路径和终点路径就是最近与两个节点之间的路径
i = 0
while i < sn and i < dn:
if self.startPath[i] == self.destPath[i]:
i += 1
else: break
startPath = self.startPath[i:]
destPath = self.destPath[i:]
# 如果没有起始路径,就返回终点路径,反之返回起始路径
# 如果都存在返回起始路径和终点路径的拼接
if not startPath: return destPath
if not destPath: return self.reversePath(startPath)
return self.reversePath(startPath) + destPath
不过上面这个做法超出时间限制了,应该是在深度优先遍历的过程中拼接起始和结束路径超时的吧,那么在这个过程中只需要记录从子节点到父节点的关系即可,然后后面的做法一致即可
class Solution:
# parent存储子节点到父节点的关系
# start为起始位置节点
# dest为结束位置节点
def __init__(self):
self.parent = {}
self.start = None
self.dest = None
# 从子节点不停的向父节点遍历,找到子节点到父节点的路径
def getPath(self, child, root):
res = []
while child != root:
parent = self.parent[child]
if child == parent.left:
res.insert(0, 'L')
else:
res.insert(0, 'R')
child = parent
return res
def getDirections(self, root: Optional[TreeNode], startValue: int, destValue: int) -> str:
# 深度优先遍历获取起始节点和结束节点,并记录子节点到父节点的关系
def dfs(root):
if not root: return
if root.val == startValue:
self.start = root
if root.val == destValue:
self.dest = root
if root.left:
self.parent[root.left] = root
dfs(root.left)
if root.right:
self.parent[root.right] = root
dfs(root.right)
dfs(root)
# 通过子节点找到其到根节点的路径
startPath = self.getPath(self.start, root)
destPath = self.getPath(self.dest, root)
# 找到起始路径和结束路径不同的位置下标,并从该位置进行字符串拼接
sn, dn = len(startPath), len(destPath)
i = 0
while i < sn and i < dn:
if startPath[i] ==destPath[i]:
i += 1
else: break
return 'U'* (sn - i) + ''.join(destPath[i:])