leetcode 257. 二叉树的所有路径 包含(二叉树的先序遍历、中序遍历、后序遍历)
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/ \
2 3
\
5
输出: ["1->2->5", "1->3"]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
首先来看递归版本:
static void dfs(TreeNode root, String path, LinkedList<String> paths){ if(root.left == null && root.right ==null){ paths.add(path + root.val); return; } if(root.left != null) { dfs(root.left, path + root.val + "->", paths); } if(root.right != null ) { dfs(root.right, path + root.val + "->", paths); } } public static List<String> binaryTreePaths(TreeNode root) { LinkedList<String> paths = new LinkedList(); //递归版本 // dfs(root, "", paths); return paths; }
那么如何将其改为非递归版本呢,我们利用后序遍历模板与先序遍历模板来实现。
解法一
static void iteration(TreeNode root, LinkedList<String> paths) { Stack<TreeNode> s = new Stack<>(); TreeNode p = root; TreeNode pre = null; while(p != null ){ s.push(p); p = p.left ; } while(!s.empty()){ p = s.peek(); if(p.right!=null && p.right != pre){ p = p.right; while(p != null ){ s.push(p); p = p.left ; } pre =null; } else{ if(pre == null ) { paths.add(getPath(s, "->")); } pre = s.pop(); } } System.out.println(); } public static List<String> binaryTreePaths(TreeNode root) { LinkedList<String> paths = new LinkedList(); //递归版本 // dfs(root, "", paths); //非递归版本 iteration(root, paths); return paths; }
private static String getPath(Stack<TreeNode> s, String sp) {
// Iterator<TreeNode> it = s.iterator();
StringBuilder buf = new StringBuilder();
// while (it.hasNext()) {
// if (buf.length() != 0) {
// buf.append(sp);
// }
// buf.append(String.valueOf(it.next().value));
// }
for(TreeNode node : s){
if (buf.length() != 0) {
buf.append(sp);
}
buf.append(String.valueOf(node.val));
}
return buf.toString();
}
解法二
class Solution { public List<String> binaryTreePaths(TreeNode root) { LinkedList<String> paths = new LinkedList(); if (root == null) return paths; LinkedList<TreeNode> node_stack = new LinkedList(); LinkedList<String> path_stack = new LinkedList(); node_stack.add(root); path_stack.add(Integer.toString(root.val)); TreeNode node; String path; while (!node_stack.isEmpty()) { node = node_stack.pollLast(); path = path_stack.pollLast(); if ((node.left == null) && (node.right == null)) paths.add(path); if (node.left != null) { node_stack.add(node.left); path_stack.add(path + "->" + Integer.toString(node.left.val)); } if (node.right != null) { node_stack.add(node.right); path_stack.add(path + "->" + Integer.toString(node.right.val)); } } return paths; } }
在这里我们用两种模板完整地实现二叉树的先序遍历,中序遍历,后序遍历。
思想一: 在从栈里弹出节点的时候,此时压入左右节点
public static void PreOrderTraversal(TreeNode root){ Stack<TreeNode> s = new Stack<>(); TreeNode p = root; s.push(p); while(!s.empty()){ TreeNode node = s.pop(); if(node == null ){ continue; } System.out.print(node.val+" "); if(node.right != null ) { s.push(node.right); } if(node.left != null ){ s.push(node.left); } } System.out.println(); } public static void PostOrderTraversal(TreeNode root){ List<Integer> res = new ArrayList<>(); Stack<TreeNode> s = new Stack<>(); TreeNode p = root; s.push(p); while(!s.empty()){ TreeNode node = s.pop(); if(node == null ){ continue; } // System.out.print(node.val+" "); res.add(node.val); if(node.left != null ) { s.push(node.left); } if(node.right != null ){ s.push(node.right); } } Collections.reverse(res); System.out.println(res); }
思想二: 从栈中弹出节点的时候,一直压入左孩子,直到为空,对于栈顶节点来说,如果有右孩子,压入右孩子,否则一直弹。
后序遍历比较特殊,对于某一节点来说,需要判断是从左右节点哪个节点访问。
public static void PreOrderWithoutRecursion(TreeNode root){ Stack<TreeNode> s = new Stack<>(); TreeNode p = root; while(p != null || !s.empty()){ if(p != null ){ System.out.print(p.val +" "); s.push(p); p = p.left ; } else{ p = s.pop(); p = p .right; } } System.out.println(); } public static void InOrderWithoutRecursion(TreeNode root){ Stack<TreeNode> s = new Stack<>(); TreeNode p = root; while(p != null || !s.empty()){ if(p != null ){ s.push(p); p = p.left ; } else{ p = s.pop(); System.out.print(p.val +" "); p = p.right; } } System.out.println(); } public static void PostOrderWithoutRecursion(TreeNode root){ Stack<TreeNode> s = new Stack<>(); TreeNode p = root; TreeNode pLastVistNode = null; while(p != null ){ s.push(p); p = p.left ; } while(!s.empty()){ p = s.pop(); if( p.right == null || p.right == pLastVistNode){ System.out.print(p.val+" "); pLastVistNode = p; } else{ s.push(p); p = p.right; while(p != null){ s.push(p); p = p.left; } } } System.out.println(); }