树的遍历总结

今天在leetcode上刷完了常见的树的遍历的题,就来总结下规律。

二叉树

层次遍历

该题目对应于 leetcode:102 二叉树的层次遍历

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/description/

思路:

既然是层次遍历,就选择使用BFS广度优先搜索来解决,BFS的核心就是队列

从根开始,如果有左孩子,就加入到队列中;如果有右孩子,就加入到队列中。

先加入左孩子再加入右孩子,只要队列中有节点,就一直循环。

代码如下:

public List<List<Integer>> levelOrder(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<>();
    List<List<Integer>> lists = new ArrayList<>();
    if(root == null) return lists;
    
    queue.add(root);
    while(!queue.isEmpty()){
        List<Integer> list = new ArrayList<>();
        int count = queue.size();
        for(int i=0;i<count;i++){
            TreeNode now = queue.poll();
            list.add(now.val);
            if(now.left != null){   
                queue.add(now.left);
            }
            if(now.right != null){
                queue.add(now.right);
            }
        }
        lists.add(list);
    }
    return lists;
}

 

层次遍历 II

该题目对应于 leetcode:107 二叉树的层次遍历 II

https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/

这道题和上一道的区别在于,这道题是从下往上的层次遍历。

解法一:

最省事的解法,就是把102的代码的lists结果用工具类Collections.reverse(lists)即可。

public List<List<Integer>> levelOrderBottom(TreeNode root){
    Queue<TreeNode> queue = new LinkedList<>();
    List<List<Integer>> lists = new ArrayList<>();
    if(root == null) return lists;
    
    queue.add(root);
    while(!queue.isEmpty()){
        List<Integer> list = new ArrayList<>();
        int count = queue.size();
        for(int i=0;i<count;i++){
            TreeNode now = queue.poll();
            list.add(now.val);
            if(now.left != null){   
                queue.add(now.left);
            }
            if(now.right != null){
                queue.add(now.right);
            }
        }
        lists.add(list);
    }
    Collections.reverse(lists);
    return lists;
}

解法二:

DFS,深度优先搜索。

public List<List<Integer>> levelOrderBottom(TreeNode root){
		
	List<List<Integer>> result = new ArrayList<>();
		
	helper(result,root,0);
		
	return result;
}
	
private void helper(List<List<Integer>> result, TreeNode root, int depth) {
	if (root==null) return;
	if (result.size()==depth) result.add(0, new ArrayList<>());
	result.get(result.size() - depth - 1).add(root.val);
	helper(result, root.left, depth + 1);
	helper(result, root.right, depth + 1);
}

前序遍历

该题目对应于 leetcode:144 二叉树的前序遍历

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

思路:

借助的特性,先将根节点加入到栈中,然后检查左子树、右子树是否为空。

public List<Integer> preorderTraversal(TreeNode root) {
    Stack<TreeNode> stack = new Stack<>();
    List<Integer> result = new ArrayList<>();
    if(root == null) return result;
    
    stack.push(root);

    while(!stack.isEmpty()){
        TreeNode now = stack.pop();
        result.add(now.val);
        // 注意,因为是栈结构,所以要先放入右子节点,然后再放入左子节点
        if(now.right != null){
            stack.push(now.right);
        }
        if(now.left != null){
            stack.push(now.left);
        }
    }
    return result;
}

中序遍历

该题目对应于 leetcode:94 二叉树的中序遍历

https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

思路:中序遍历,即左根右。还是借助结构。那么,我们就要换一种思路,用一个指针去遍历,看左子节点有没有孩子,有的话就加入栈中,没有,就将父节点取出,将值加入到数组中,然后再指向右子节点。

public List<Integer> inorderTraversal(TreeNode root) {
    Stack<Integer> stack = new Stack<>();
    List<Integer> result = new ArrayList<>();
    if(root == null) return result;

    TreeNode now = root;

    while(now != null && !stack.isEmpty()){
        if(now != null){
            stack.push(now);
            now = now.left;
        } else {
            now = stack.pop();
            result.add(now.val);
            now = now.right;
        }
    }
    return result;
}

后序遍历

该题目对应于 leetcode:145 二叉树的后序遍历

https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

思路:和前序遍历类似,结果反转。

public List<Integer> postorderTraversal(TreeNode root) {
	Stack<TreeNode> stack = new Stack<>();
	List<Integer> output = new ArrayList<>();
	if (root == null) return output;
	
	stack.add(root);
	while (!stack.isEmpty()) {
		TreeNode now = stack.pop();
		output.add(now.val);
		if (now.left != null) {
			stack.push(now.left);
		}
		if (now.right != null) {
			stack.push(now.right);
		}
	}
	Collections.reverse(output);
	return output;
}

 

深度

最大深度

该题目对应于 leetcode:104 二叉树的最大深度

https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

思路:DFS递归,递归终止条件:节点为空。

public int maxDepth(TreeNode root) {
    if(root == null) {
        return 0;
    } else {
        int left_depth = maxDepth(root.left);
        int right_depth = maxDepth(root.right);
        return Math.max(left_depth,right_depth) + 1;
    } 
}

最小深度

该题目对应于 leetcode:111 二叉树的最小深度

https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/submissions/

思路:DFS递归。

public int minDepth(TreeNode root) {
    if(root == null) return 0;
    if(root.left == null && root.right == null) return 1;
    
    int min_depth = Integer.MAX_VALUE;
    if(root.left != null){
        min_depth = Math.min(min_depth,minDepth(root.left));
    }
    if(root.right != null){
        min_depth = Math.min(min_depth,minDepth(root.right));
    }
   
    return min_depth + 1;
}

N叉树

层次遍历

该题目对应于 leetcode:429 N叉树的层序遍历

https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/submissions/

思路:一般只有层次遍历才会使用到队列,即BFS广度优先搜索。

public List<List<Integer>> levelOrder(Node root) {
    Queue<Node> queue = new LinkedList<>();
    List<List<Integer>> result = new ArrayList<>();
    if(root == null) return result;

    queue.add(root);
    while(!queue.isEmpty()){
        int count = queue.size();
        List<Integer> list = new ArrayList<>();
        for(int i=0;i<count;i++){
            Node now = queue.poll();
            list.add(now.val);
            for(Node child : now.children){
                queue.add(child);
            }
        }
        result.add(list);
    }
    return result;
}

前序遍历

该题目对应于 leetcode:589 N叉树的前序遍历

https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/

思路:借助结构,类似于二叉树的前序遍历。

public List<Integer> preorder(Node root) {
    Stack<Node> stack = new Stack<>();
    List<Integer> result = new ArrayList<>();
    if(root == null) return result;

    stack.push(root);
    
    while(!stack.isEmpty()){
        Node now = stack.pop();
        result.add(now.val);
        List<Node> nodes = now.children;
        for(int i=nodes.size()-1;i>=0;i--){
            stack.push(nodes.get(i));
        }
    }
    return result;
}

后序遍历

该题目对应于 leetcode:590 N叉树的后序遍历

https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal/

思路:类似于前序遍历,借助结构。

public List<Integer> postorder(Node root) {
    Stack<Node> stack = new Stack<>();
    List<Integer> result = new ArrayList<>();
    if(root == null) return result;    

    stack.push(root);

    while(!stack.isEmpty()){
        Node now = stack.pop();
        result.add(0,now.val);
        for(Node child : now.children){
            stack.push(child);
        }
    }

    return result;
}

最大深度

该题目对应于 leetcode:559 N叉树的最大深度

https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/submissions/

思路:利用队列,迭代。 

public int maxDepth(Node root) {
    Queue<Node> queue = new LinkedList<>();
    if(root == null) return 0;
    
    queue.add(root);
    int max = 0;
    while(!queue.isEmpty()){
        max++;
        int count = queue.size();
        while(count-- >0){
            Node now = queue.poll();
            for(Node child : now.children){
                queue.add(child);
            }
        }
    }
    return max;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值