標籤:
轉載請註明出處:http://blog.csdn.net/crazy1235/article/details/51474128
Subject
出處:https://leetcode.com/problems/binary-tree-paths/
Given a binary tree, return all root-to-leaf paths.For example, given the following binary tree: 1 / \2 3 \ 5All root-to-leaf paths are:["1->2->5", "1->3"]
Explain
該題目是求一顆二叉樹的所有路徑(從根結點到每個葉子結點)。
返回所有路徑組成的List集合。
Solutionsolution 1
最容易想到的方法就是遞迴。
深度優先遍曆 — DFS。
public List<String> resultList = new ArrayList<String>();
/** * 遞迴方式 * * <br /> * * Run Time : 4ms * * @param root * @return */ public List<String> binaryTreePaths(TreeNode root) { if (root == null) { return resultList; } List<String> singleResult = new ArrayList<>(); getTreePath(root, singleResult); return resultList; }
/** * DFS * * @param resultList * @param node * @param singleResult */ private void getTreePath(TreeNode node, List<String> singleResult) { singleResult.add(node.val + ""); if (node.left == null && node.right == null) { resultList.add(getPath(singleResult)); } if (node.left != null) { getTreePath(node.left, new ArrayList<>(singleResult)); } if (node.right != null) { getTreePath(node.right, new ArrayList<>(singleResult)); } }
恩,這是最容易想到的方法。
我還想到了用棧來解決,但是沒寫出來,囧~~~
solution 2
方法二,與方法一類似。
參考 : https://leetcode.com/discuss/85025/sharing-my-recursive-java-solution
public List<String> binaryTreePaths2(TreeNode root) { if (root == null) { return resultList; } findPaths(root, root.val + ""); return resultList; } private void findPaths(TreeNode node, String path) { if (node.left == null && node.right == null) { resultList.add(path); } if (node.left != null) { findPaths(node.left, path + "->" + node.left.val); } if (node.right != null) { findPaths(node.right, path + "->" + node.right.val); } }
也是通過遞迴解決。
不過單條路徑不需要通過一個List集合來儲存,直接通過字串構造出來。
solution 3
在方法二的基礎上,將String改為StringBuilder效率更高一些。
該方法利用了StringBuilder類的setLength()方法。
so clever ~
public List<String> binaryTreePaths3(TreeNode root) { findPath(root, new StringBuilder()); return resultList; } private void findPath(TreeNode node, StringBuilder sb) { if (node == null) { return; } int len = sb.length(); sb.append(node.val); if (node.left == null && node.right == null) { resultList.add(sb.toString()); } else { sb.append("->"); findPath(node.left, sb); findPath(node.right, sb); } sb.setLength(len);// 截取 !!! }
該方法在LeetCode平台上測試回合時間是2ms。
solution 4
通過棧的方式來做。
哈哈哈。
棧
參考 : https://leetcode.com/discuss/83013/my-java-non-recursion-solution-using-stack-and-wrapper
public List<String> binaryTreePaths4(TreeNode root) { if (root == null) { return resultList; } Stack<Wrapper> stack = new Stack<>(); stack.add(new Wrapper(root, root.val + "")); Wrapper wrapper = null; while (!stack.isEmpty()) { wrapper = stack.pop(); if (wrapper.node.left == null && wrapper.node.right == null) { resultList.add(wrapper.path); } if (wrapper.node.left != null) { stack.add(new Wrapper(wrapper.node.left, wrapper.path + "->" + wrapper.node.left.val)); } if (wrapper.node.right != null) { stack.add(new Wrapper(wrapper.node.right, wrapper.path + "->" + wrapper.node.right.val)); } } return resultList; }
private static class Wrapper { TreeNode node; String path; public Wrapper() { } public Wrapper(TreeNode node) { this.node = node; } public Wrapper(TreeNode node, String path) { this.node = node; this.path = path; } }
需要一個類進行封裝,裡面儲存當前結點,和訪問到此結點的路徑。
如果純看代碼看不懂,直接斷點跟蹤一下明白了。
該方法Run Time 是 5ms
solution 5
既然DFS可以實現,估計BFS也可以的。
恩。是可以的~~
參考 : https://leetcode.com/discuss/67749/bfs-with-two-queue-java-solution
/** * BFS * with two Queue * @param root * @return */ public List<String> binaryTreePaths5(TreeNode root) { if (root == null) { return resultList; } Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>(); Queue<String> pathQueue = new LinkedList<>(); nodeQueue.offer(root); pathQueue.offer(root.val + ""); while (!nodeQueue.isEmpty()) { TreeNode currNode = nodeQueue.poll(); String item = pathQueue.poll(); if (currNode.left == null && currNode.right == null) { resultList.add(item); } if (currNode.left != null) { nodeQueue.offer(currNode.left); pathQueue.offer(item + "->" + currNode.left.val); } if (currNode.right != null) { nodeQueue.offer(currNode.right); pathQueue.offer(item + "->" + currNode.right.val); } } return resultList; }
通過兩個隊列:
一個儲存結點
一個儲存訪問到此節點的路徑
單條路徑結束的判斷條件依舊是當前結點是葉子結點。
該方法Run Time 耗時是 4ms。
solution 6
該方法的思想依舊是遞迴操作。
不過不需要額外建立一個函數去遞迴調用。
直接遞迴調用提供的函數即可。
參考:https://leetcode.com/discuss/55451/clean-solution-accepted-without-helper-recursive-function
public List<String> binaryTreePaths6(TreeNode root) { List<String> pathsList = new ArrayList<String>(); if (root == null) { return pathsList; } if (root.left == null && root.right == null) { pathsList.add(root.val + ""); return pathsList; } for (String path : binaryTreePaths6(root.left)) { pathsList.add(root.val + "->" + path); } for (String path : binaryTreePaths6(root.right)) { pathsList.add(root.val + "->" + path); } return pathsList; }
yes.
該方法Run Time 是 3ms。
源碼請移步:github.
https://github.com/crazy1235/BaseJavaProject/blob/master/BaseJavaProject/src/com/jacksen/java/leetcode/BinaryTreePaths.java
bingo~~
【LeetCode】257. Binary Tree Paths 解題報告