剑指offer32Ⅰ:从上到下打印二叉树

    题目描述

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:

给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
      /  \
   15   7
   
返回其层次遍历结果:

[3,9,20,15,7]

提示:

节点总数 <= 1000

   思路

     这个题目的意思很明确,就是从根节点开始,一层一层打印节点,而且节点顺序是从左到右。以上面示例为例,3为根节点,之后打印它的左右节点9,20,之后再打印20的子节点15,7。全部打印完成结束。

   这道题有点类似图算法中的广度优先搜索,先从顶端开始,依次遍历图的下一层节点,下一层节点遍历完成,接着遍历下下一层。仅仅依赖树结构的左右节点关系,然后递归遍历,我们无法得到最终结果,因为随着层数的增加,兄弟节点之间没有必然关系,他们无法保证从左到右来遍历。

    这里我们需要借助一个队列来存放遍历过的节点,这样,每遍历依次,后续的遍历,我们从队列开头取元素,这样就可以保证按照层级和左右顺序来打印树节点。

 代码

package com.xxx.example;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Offer32PrintTreeNode {
    private static TreeNode root;
    private static List<List<Integer>> nodeList = new ArrayList<>();

    public static void main(String[] args) {
        TreeNode treeNode = new TreeNode(3);
        TreeNode treeNode1 = new TreeNode(9);
        TreeNode treeNode2 = new TreeNode(20);
        TreeNode treeNode3 = new TreeNode(15);
        TreeNode treeNode4 = new TreeNode(7);
        root = treeNode;
        treeNode2.left = treeNode3;
        treeNode2.right = treeNode4;
        root.left = treeNode1;
        root.right = treeNode2;

        int[] result = levelOrder(root);

        for(int i=0;i<result.length;i++) {
            System.out.print(result[i] + " ");
        }
        System.out.println();

    }

    public static int[] levelOrder(TreeNode root) {
        if (root == null)
            return new int[0];
        Queue<TreeNode> queue = new LinkedList<>();
        ArrayList<Integer> list = new ArrayList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode curNode = queue.poll();
            list.add(curNode.val);
            if (curNode.left != null)
                queue.add(curNode.left);
            if (curNode.right != null)
                queue.add(curNode.right);
        }
        return list.stream().mapToInt(Integer::intValue).toArray();
    }


}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int value) {
        this.val = value;
        this.left = null;
        this.right = null;
    }

    @Override
    public String toString() {
        return val + "";
    }
}

    还有一种办法,其实就是利用深度优先搜索的思想解决,这个似乎有点玄妙,这里明明是要广度优先搜索,怎么还利用起深度优先搜索呢?其实是这样的,这里按照深度优先搜索,我们只是把搜到的数据打上标签,这个标签就是它的层次,也叫深度,每个深度的节点我们保存到同样深度的map映射里。最后,我们遍历map,得到所有按照层次组织的节点,这样就是从上到下,从左到右打印二叉树节点。 

深度优先搜索 


package com.xxx.tutorial;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TreeNodeTraversal {

    private static Map<Integer, List<Integer>> map = new HashMap<>();
    private static int max = -1;
    private static int cnt = 0;

    public static void main(String[] args) {
        TreeNode node0 = new TreeNode(3);
        TreeNode node1 = new TreeNode(9);
        TreeNode node2 = new TreeNode(20);
        TreeNode node3 = new TreeNode(15);
        TreeNode node4 = new TreeNode(7);

        node0.left = node1;
        node0.right = node2;
        node2.left = node3;
        node2.right = node4;
        int[] res = traversal(node0);
        for (int i = 0; i < res.length; i++) {
            System.out.print(res[i] + " ");
        }
        System.out.println();
    }

    public static int[] traversal(TreeNode root) {
        dfs(root, 0);
        int[] ans = new int[cnt];
        for (int i = 0, idx = 0; i <= max; i++) {
            for (int x : map.get(i))
                ans[idx++] = x;
        }
        return ans;
    }

    public static void dfs(TreeNode node, int depth) {
        if (node == null) return;
        max = Math.max(max, depth);
        cnt++;
        dfs(node.left, depth + 1);
        List<Integer> list = map.getOrDefault(depth, new ArrayList<>());
        list.add(node.val);
        map.put(depth, list);
        dfs(node.right, depth + 1);
    }

    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int value) {
            this.val = value;
            this.left = null;
            this.right = null;
        }
    }
}

    这里通过递归调用,我们能遍历完所有节点,并按照深度层次保存各自深度的节点。 

    这个思路很巧妙,它利用深度层次来映射对应的节点,最后,我们遍历map映射得到所有节点,他们的顺序正好是从上到下,从左到右。

    剑指offer打印二叉树还有另一个题目,就是按照层次打印二叉树,就是[[3],[9,20],[15,7]],相信经过上面的深度优先搜索,大家也许有一些想法,这个代码或许简单改造一下就可以了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值