1.递归
递归时间复杂度:O(N),N为二叉树结点的个数
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root != null){
res.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
}
return res;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
用递归固然简单,但递归栈的栈深为树的深度,如果遍历一颗单支树,就会得到最坏的空间复杂度O(logN),空间平均复杂度为O(logN),我们可以利用栈来消除递归。
2.先序遍历的非递归实现:
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode p = root;
while (p != null || !stack.isEmpty()) {
if (p != null) { //一直走到最左下
res.add(p.val); //访问节点后,压栈
stack.add(p);
p = p.left;
} else { //当前栈内节点没有左子树了,那么就访问右孩子节点,右孩子有可能有左子树,用相同的方法处理
p = stack.pop();
p = p.right;
}
}
return res;
}
}
还有一种更直观的方法:
void preorder(Node* root) {
stack<Node*> myStack;
Node* p;
if(root==NULL)return;
myStack.push(root);
while(!myStack.empty())
{
p=myStack.top();
myStack.pop();
visit(p); 处理
if(p->right!=NULL){myStack.push(p->right);}
if(p->left!=NULL){myStack.push(p->left);}
}
1.递归实现:
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root != null){
inorderTraversal(root.left);
res.add(root.val);
inorderTraversal(root.right);
}
return res;
}
}
2.非递归实现:
和先序遍历不同的是将左孩子压栈的时候先不访问根节点,等到弹栈的时候再访问根节点,然后再将右孩子压入栈。
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
if(root == null) {
return res;
}
TreeNode cur = root;
while(cur != null || !stack.isEmpty()) {
while(cur!= null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
return res;
}
}
1.递归实现:
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root != null){
postorderTraversal(root.left);
postorderTraversal(root.right);
res.add(root.val);
}
return res;
}
}
2.非递归实现:
后序遍历比前两种遍历的非递归实现都要复杂。原因是,我们访问完左节点后,弹栈时并不能立即访问根节点的值,因为遍历顺序为:左->右->根,在访问根节点之前,我们还要确定根节点的右子树是否已经被访问过。
- 设一个标记节点tag,对于将要弹栈的节点,判断一下这个节点是从左孩子节点还是右孩子节点来的。
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
if(root == null) {
return res;
}
TreeNode cur = root; // 当前节点
TreeNode tag = null; // 标记节点:标记当前节点是从左/右孩子来的
while(cur != null || !stack.isEmpty()) {
if(cur != null) { //当前节点不为空,压栈,再看左孩子是否为空,不空继续压栈
stack.push(cur);
cur = cur.left;
}else { //访问右孩子
cur = stack.peek();
//当前节点右子树不为空,并且右子树没有访问过
if(cur.right != null && cur.right != tag) {
cur = cur.right;
stack.push(cur);
cur = cur.left;
}else { //没有右子树,或者已经访问过了,就访问根节点
cur = stack.pop();
res.add(cur.val);
tag = cur; //修改标记
cur = null;
}
}
}
return res;
}
}
BFS
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
if(root == null)
return res;
Queue<TreeNode> qu = new LinkedList<>();
qu.offer(root);
while(!qu.isEmpty()) {
int size = qu.size();
List<Integer> level = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode cur = qu.poll();
if(cur.left != null)
qu.offer(cur.left);
if(cur.right != null)
qu.offer(cur.right);
level.add(cur.val);
}
res.add(level);
}
return res;
}
/*
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}*/
}
//C++版本
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root){ //空树
return res;
}
queue<TreeNode*> qu;
qu.push(root);
while(!qu.empty()){
int size = qu.size();
res.push_back(vector <int> ());
for(int i = 1; i <= size; i++){
auto node = qu.front();
qu.pop();
res.back().push_back(node->val);
if(node->left) qu.push(node->left);
if(node->right) qu.push(node->right);
}
}
return res;
}
};
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
if(root == null)
return res;
Queue<TreeNode> qu = new LinkedList<>();
qu.offer(root);
while(!qu.isEmpty()) {
int size = qu.size();
List<Integer> level = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode cur = qu.poll();
if(cur.left != null)
qu.offer(cur.left);
if(cur.right != null)
qu.offer(cur.right);
level.add(cur.val);
}
res.add(0, level); //实际上还是从上往下BFS,不过添加的时候是在0处添加
}
return res;
}
}
也可以用addfirst(头插),一个意思。
利用层次遍历计算每一层的平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new LinkedList<>();
if(root == null)
return res;
Queue<TreeNode> qu = new LinkedList<>();
qu.offer(root);
while(!qu.isEmpty()) {
int size = qu.size();
double sum = 0;
for (int i = 0; i < size; i++) {
TreeNode cur = qu.poll();
if(cur.left != null)
qu.offer(cur.left);
if(cur.right != null)
qu.offer(cur.right);
sum += cur.val;
}
res.add(sum/size);
}
return res;
}
}