二叉树类的定义:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
144. 二叉树的前序遍历
遍历顺序: 根-左-右
方法一 递归
class Solution {
List<Integer> list = new LinkedList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null)return list;
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
}
方法二 迭代
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
if(root == null)return list;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(!stack.empty() || cur!=null){
while(cur!=null){
stack.push(cur);
list.add(cur.val); //插入节点值
cur = cur.left;
}
cur = stack.pop();
cur = cur.right;
}
return list;
}
}
(取自网图)
前序遍历和中序遍历的区别在于何时将树节点值加入链表List,即 List.add(cur,val) ,前序遍历在节点入栈时将节点值插入,中序遍历在节点出栈时将节点值插入。
前序、中序遍历思路:
设置遍历节点cur,从根节点开始。
一. 依次入栈左子树根节点直至为空;
1,2,4依次入栈
二. 栈顶出栈,遍历该节点右子树,重复步骤一;
4出栈,2出栈,5入栈,5出栈,1出栈,3入栈,6入栈,3出栈,7入栈
94. 二叉树的中序遍历
遍历顺序: 左-根-右
方法一 递归
class Solution {
List<Integer> list = new LinkedList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root == null)return list;
inorderTraversal(root.left);
list.add(root.val);
inorderTraversal(root.right);
return list;
}
}
方法二 迭代
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
if(root == null)return list;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(!stack.empty() || cur!=null){
while(cur!=null){
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
list.add(cur.val); //插入节点值
cur = cur.right;
}
return list;
}
}
145. 二叉树的后序遍历
遍历顺序: 左-右-根
方法一 递归
class Solution {
List<Integer> list = new LinkedList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root == null)return list;
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
}
方法二 迭代
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
if(root == null)return list;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(!stack.empty() || cur!=null){
while(cur!=null){
stack.push(cur);
list.add(cur.val); //插入节点值
cur = cur.right; //先右
}
cur = stack.pop();
cur = cur.left; // 后左
}
Collections.reverse(list);
//or LinkedList<> list = new LinkedList<>(); list.addFirst();
return list;
}
}
后序遍历顺序为:左-右-根
而前序遍历顺序为:根-左-右,将前序的遍历顺序更改为:根-右-左,将链表反转后输出,此时输出顺序恰好为左右根,符合后序遍历
三类遍历时间空间复杂度:
时间复杂度:O(n),n为树的节点个数
空间复杂度:O(n),平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。
102. 二叉树的层序遍历
输出顺序: 1,2,3,4,5,6,7
输出格式:[[1],[2,3],[4,5,6,7]]
运用BFS思想遍历(BFS还应用于最短路径搜索)
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> output = new ArrayList<>();
if(root == null)return output;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int n = queue.size();
ArrayList<Integer> list = new ArrayList<>();
for(int i=0; i<n; i++){
TreeNode temp = queue.poll();
if(temp.left!=null)queue.offer(temp.left);
if(temp.right!=null)queue.offer(temp.right);
list.add(temp.val);
}
output.add(list);
}
return output;
}
}
层次遍历思路:
借助队列先进先出的特性,依次入队二叉树的每一层节点,从根节点开始入队
一. 出队,将节点值插入List,依次入队该节点的左右子节点;
1入队;1出队,2,3入队;2出队,4,5入队,3出队,6,7入队;4,5,6,7出队.
二. 重复步骤一直至队列为空;
时间空间复杂度:
时间复杂度:每个点进队出队各一次,故渐进时间复杂度为 O(n)。
空间复杂度:队列中元素的个数不超过 n 个,故渐进空间复杂度为 O(n)。
PS:代码思路均来自LeetCode解析