记录算法学习,输出更有利于学习!欢迎一起讨论。
257. 二叉树的所有路径
给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点
例子 :
题目中需要找到所有的子叶节点的路径,并且输出路径。因此需要把路径记录下来,并且回溯退回到下一个子节点的路径中去。
在树中回溯法(递归)
如图:
回溯三个步骤:
- 确定传入的参数。 只需要传入 root 即可。
function backtracking(root) {}
- 终止条件。 子叶节点就是左右节点都为 null。所以终止条件为
if(root.left === null && root.right === null) {
// 终止的逻辑
return
}
- 单层遍历逻辑。 判断是否有节点,然后递归,回溯。按照一个前序遍历的方式进行。 有一个递归,就要有一个回溯,树节点中是左右两个递归分开进行,所以需要两边都需要回溯一下。
path.push(root.val)
if(root.left) {
trackbacking(root.left)
path.pop()
}
if(root.right) {
trackbacking(root.right)
path.pop()
}
完整代码
var binaryTreePaths = function(root) {
// 递归,
let res = [], path = []
const trackbacking = function(root) {
// 1,参数,root.
path.push(root.val)
// 2,终止条件, 如果找到叶子节点,返回路径
if(root.left === null && root.right === null) {
res.push(path.join('->'))
return
}
// 3. 单层逻辑,递归,回溯
if(root.left) {
trackbacking(root.left)
path.pop()
}
if(root.right) {
trackbacking(root.right)
path.pop()
}
}
trackbacking(root)
return res
};
进阶 - 简化版本
递归回溯中,使用引用数组的方式去存储结果, 所以需要重复的写 path.pop()
可以改成字符串传入的方式去实现。
var binaryTreePaths = function(root) {
// 递归,
let res = []
const trackbacking = function(root,curPath) {
// 1,参数,root. curpath , 路径字符串
// 2,终止条件, 如果找到叶子节点,返回路径
if(root.left === null && root.right === null) {
// 在找到子叶节点后,添加,不需要 '->'
curPath += root.val;
res.push(curPath)
return
}
// 3. 单层逻辑, 使用赋值的方式,并且传入递归中,这样递归中拿到的路径是单独的,而且在return 出来的时候 当前层级的节点还是不变的,也暗含了 回溯。
curPath += root.val + '->'; // 非子叶节点需要加 ->
root.left && trackbacking(root.left, curPath)
root.right && trackbacking(root.right, curPath)
}
trackbacking(root,'')
return res
};