您的位置:首页 > 其它

[lintcode] Binary Tree Preorder Traversal

2015-10-06 10:45 295 查看
Binary Tree Preorder Traversal

Given a binary tree, return the preorder traversal of its nodes' values.

Example

Given binary tree
{1,#,2,3}
:

1
\
2
/
3

return
[1,2,3]
.

SOLUTION 1:

这题首先应该想到递归做法,最简单直观的也是递归做法。首先先来说一下递归是什么,递归其实就是自己调用自己,但是注意的是,递归往往没有返回值。

在用递归方法的时候要定义清楚,递归方法接收了什么参数,做了什么事情,在这个题里面,看到返回值是个ArrayList,那么首先应该new一个存放结果的ArrayList并且用于最后返回,

所以说递归函数一定会接受一个ArrayList,而且一定会有一个根结点,所以这个递归函数应该是这样的:traversal(TreeNode root, ArrayList<Integer> result){},然后定义这个函数做了什么事情,就是把以root为根的前序遍历加到result里面。

时间复杂度分析:每个点只操作一次,一次操作都是O(1)的,所以总的时间复杂度就是O(N),其中N是二叉树中点的个数。

后面就很简单的看一下代码了:

public class Solution {
/**
* @param root: The root of binary tree.
* @return: Preorder in ArrayList which contains node values.
*/
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (root == null){
return result;
}
traversal(root, result);
return result;
}
private void traversal(TreeNode root, ArrayList<Integer> result){
if (root == null){
return;
}
result.add(root.val);
traversal(root.left, result);
traversal(root.right, result);
}
}


  

SOLUTION 2:

第二种方法,就是几乎使用所有二叉树的分治法,分治法其实也是一种递归方法,不过相当于把给的参数分成两部分,分别处理,在二叉树这种结构中,天然的把自己分成了两个部分,可以直接使用分治法。

注意的是分治法一般都是有返回值的,这个跟一般的递归方法是不一样的。

时间复杂度分析:Divide部分,时间复杂度还是O(N),因为每个点还是只遍历一次;但是在Conquer里面,用数组result.add这个操作的时间复杂度太费了,可能是O(N),总的时间复杂度可能就退化成了O(N^2)了,当然也可以用链表优化,这样conquer的操作就也是O(1)的了。

代码如下:

public class Solution {
/**
* @param root: The root of binary tree.
* @return: Preorder in ArrayList which contains node values.
*/
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (root == null){
return result;
}
// 左右两边分别递归处理===》分治法之“分”
ArrayList<Integer> left = preorderTraversal(root.left);
ArrayList<Integer> right = preorderTraversal(root.right);
// 左右两边再跟根结点合并
result.add(root.val);
result.addAll(left);
result.addAll(right);
return result;
}
}


SOLUTION 3:

比较重要的是第三种方法,这种方法是非递归方法。

对于递归方法,它的一个坏处就是会stack overflow,就是栈溢出,这个是由于当运行一个程序的时候,系统会自动分配给这个程序一块栈内存,8MB,也就是说,递归过深的时候,就会消耗大量栈空间,当其超过8MB时候就会栈溢出,所以,往往能用非递归就不用递归,除非非递归太复杂了。

非递归的解体方法就是用栈(stack)模拟递归。具体方法见代码:

public class Solution {
/**
* @param root: The root of binary tree.
* @return: Preorder in ArrayList which contains node values.
*/
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while (!stack.empty()){
TreeNode temp = stack.pop();
result.add(temp.val);
// 由于stack是先进后出,所以压栈时候要先压入right子树
// 这样才能保证出栈时候是左先出,右后出
if (temp.right != null){
stack.push(temp.right);
}
if (temp.left != null){
stack.push(temp.left);
}
}
return result;
}
}


  

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: