【LeetCode】Explore.Learn.Binary Tree

一、 Traverse a tree


  1. Binary Tree Preorder Traversal

思路:

递归法很简单,不赘述。迭代法:先序遍历可分解为两段,沿最左侧通路自顶向下访问的各节点,以及自底向上遍历的对应右子树。

代码:

    private void visitAlongLeftBranch(TreeNode node, Stack<TreeNode> st, List<Integer> res) {
        while (node != null) {
            res.add(node.val);
            st.push(node.right);
            node = node.left;
        }

    }
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> st = new Stack<>();

        TreeNode x = root;
        while (true) {
            visitAlongLeftBranch(x, st, res);
            if (st.empty()) break;
            x = st.pop();
        }

        return res;
    }


  1. Binary Tree Inorder Traversal

思路:

递归法很简单,不赘述。迭代法:沿最左侧通路自底向上,以沿途各节点为界,遍历其右子树。

代码:

   private void goAlongLeftBranch(TreeNode node, Stack<TreeNode> st) {
       while (node != null) {
           st.push(node);
           node = node.left;
       }
   }
   public List<Integer> inorderTraversal(TreeNode root) {
       List<Integer> res = new ArrayList<>();
       Stack<TreeNode> st = new Stack<>();

       TreeNode x = root;

       while (true) {
           goAlongLeftBranch(x, st);
           if (st.empty()) break;
           x = st.pop();
           res.add(x.val);
           x = x.right;
       }
       return res;
   }

  1. Binary Tree Postorder Traversal

思路:

递归法解决,迭代法过于麻烦,按下不表。

代码:

    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        inorder(res, root);
        return res;
    }

    private void inorder(List<Integer> res, TreeNode node) {
        if (node == null) {
            return;
        }

        inorder(res, node.left);
        inorder(res, node.right);
        res.add(node.val);
    }

二、Solve Tree Problems Recursively


  1. Maximum Depth of Binary Tree

思路:

比较简单,不赘述。

代码:

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

  1. Symmetric Tree

思路:

比较简单,不赘述。

代码:

    public boolean isSymmetric(TreeNode root) {
        return root == null || isSymmetricHelp(root.left, root.right);
    }

    private boolean isSymmetricHelp(TreeNode left, TreeNode right) {
        if (left == null || right == null)
            return left == right;
        if (left.val != right.val)
            return false;
        return isSymmetricHelp(left.left, right.right) && isSymmetricHelp(left.right, right.left);
    }

  1. Path Sum

思路:

比较简单,不赘述。

代码:

    public boolean hasPathSum(TreeNode root, int sum) {
        if (root == null) return false;
        return preorder(root, 0, sum);
    }

    private boolean preorder(TreeNode node, int sum, int target) {
        if (node == null) return false;


        if (node.left == null && node.right == null && (sum + node.val) == target) {
            return true;
        }

        return preorder(node.left, sum + node.val, target) || preorder(node.right, sum + node.val, target);
    }

三、Conclusions


  1. Construct Binary Tree from Inorder and Postorder Traversal

思路:

代码:

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        TreeNode root = build(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
        return root;
    }

    private TreeNode build(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
        if(inStart > inEnd || postStart > postEnd) return null;
        TreeNode node = new TreeNode(postorder[postEnd]);

        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == postorder[postEnd]) {
                node.left = build(inorder, inStart, i - 1, postorder, postStart, postStart + (i - inStart) - 1);
                node.right = build(inorder, i + 1, inEnd, postorder, postStart + (i - inStart), postEnd - 1);
            }
        }

        return node;
    }

  1. Construct Binary Tree from Preorder and Inorder Traversal

思路:

代码:

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        TreeNode root = build(inorder, 0, inorder.length - 1, preorder, 0, preorder.length - 1);
        return root;
    }

    private TreeNode build(int[] inorder, int inStart, int inEnd, int[] preorder, int preStart, int preEnd) {
        if(inStart > inEnd || preStart > preEnd) return null;
        TreeNode node = new TreeNode(preorder[preStart]);

        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == preorder[preStart]) {
                node.left = build(inorder, inStart, i - 1, preorder, preStart + 1, preStart + (i - inStart));
                node.right = build(inorder, i + 1, inEnd, preorder, preStart + (i - inStart) + 1, preEnd);
            }
        }

        return node;
    }

  1. Populating Next Right Pointers in Each Node

思路:

可以在层序遍历的基础上改进,也可以递归解决,详情见代码。

代码:

层序遍历改进:

    public void connect(TreeLinkNode root) {
        Queue<TreeLinkNode> queue = new LinkedList<>();
        List<List<TreeLinkNode>> wrapList = new LinkedList<>();

        if (root == null) return;

        queue.offer(root);
        while (!queue.isEmpty()) {
            int levelNum = queue.size();
            List<TreeLinkNode> subList = new LinkedList<>();
            for (int i = 0; i < levelNum; i++) {
                if (queue.peek().left != null) queue.offer(queue.peek().left);
                if (queue.peek().right != null) queue.offer(queue.peek().right);
                subList.add(queue.poll());
            }
            wrapList.add(subList);
        }

        for (int i = 0; i < wrapList.size(); i++) {
            for (int j = 0; j < wrapList.get(i).size() - 1; j++) {
                wrapList.get(i).get(j).next = wrapList.get(i).get(j + 1);
            }

            if (wrapList.get(i).size() == 1) {
                wrapList.get(i).get(0).next = null;
            }
        }
    }

递归:

    public void connect(TreeLinkNode root) {
        connect(root, null);
    }

    private static void connect(TreeLinkNode root, TreeLinkNode sibling) {
        if (root == null) return;
        else root.next = sibling;

        connect(root.left, root.right);
        if (sibling != null) connect(root.right, sibling.left);
        else connect(root.right, null);
    }

  1. Lowest Common Ancestor of a Binary Tree

思路:

当前节点如果是p,q的公共最先节点,则p,q一定在当前节点的左右子树中。可以用递归解决。

代码:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q) return root;

        TreeNode ltree = lowestCommonAncestor(root.left, p, q);
        TreeNode rtree = lowestCommonAncestor(root.right, p, q);

        if (ltree != null && rtree != null) return root;

        return ltree != null ? ltree : rtree;

    }

  1. Serialize and Deserialize Binary Tree

思路:

注意是如果是preorder的serialize,那就要对应的deserialize,不难。

代码:

    // Encodes a tree to a single string.
    public String serialize(TreeNode root)
    {
        if(root == null) return "#";

        return "" + root.val + " " + serialize(root.left) + " " + serialize(root.right);
    }


    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data)
    {
        return build(new Scanner(data));
    }

    private TreeNode build(Scanner sc)
    {
        if(!sc.hasNext()) return null;
        String tk = sc.next();
        if(tk.equals("#")) return null;

        TreeNode root = new TreeNode(Integer.parseInt(tk));
        root.left = build(sc);
        root.right = build(sc);

        return root;
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,104评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,816评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,697评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,836评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,851评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,441评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,992评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,899评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,457评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,529评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,664评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,346评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,025评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,511评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,611评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,081评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,675评论 2 359

推荐阅读更多精彩内容