转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51474128
Subject
Given a binary tree, return all root-to-leaf paths.
For example, given the following binary tree:
1
/ \
2 3
\
5
All root-to-leaf paths are:
["1->2->5", "1->3"]
Explain
该题目是求一颗二叉树的所有路径(从根结点到每个叶子结点)。
返回所有路径组成的List集合。
Solution
solution 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.
bingo~~