Leetcode - Construct Binary Tree from Preorder and Inorder Traversal

My code:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length == 0)
            return null;
        if (inorder == null || inorder.length == 0)
            return null;
        if (preorder.length != inorder.length)
            return null;
        return buildTree(0, preorder.length - 1, 0, inorder.length - 1, preorder, inorder); 
    }
    
    private TreeNode buildTree(int preorderBegin, int preorderEnd, int inorderBegin, int inorderEnd, int[] preorder, int[] inorder) {
        if (preorderEnd > preorderBegin || inorderEnd > inorderBegin)
            return null;
        else if (preorderBegin == preorderEnd)
            return new TreeNode(preorder[preorderBegin]);
        TreeNode root = new TreeNode(preorder[preorderBegin]);
        int rootIndex = 0;
        for (int i = inorderBegin; i <= inorderEnd; i++) {
            if (inorder[i] == preorder[preorderBegin]) {
                rootIndex = i;
                break;
            }
        }
        int leftTreeSize = rootIndex - inorderBegin;
        root.left = buildTree(preorderBegin + 1, preorderBegin + leftTreeSize, inorderBegin, rootIndex - 1, preorder, inorder);
        root.right = buildTree(preorderBegin + leftTreeSize + 1, preorderEnd, rootIndex + 1, inorderEnd, preorder, inorder);
        return root;
    }
}

My test result:

Paste_Image.png

这道题目做了大概一个多小时,还没做出来。因为我的意识一开始出了问题,考虑错了一个东西。然后后期发现了,但是逻辑已经乱了,很难再次阻止有效的进攻了。

哪里错了呢? 两点。
preorder 的范围 [begin, end] 并不是 inorder 的范围,如果直接拿begin, end 来作为inorder[] 数组的边界条件,就会出错。所以必须要分为两个范围。
[preorderBegin, preorderEnd]
[inorderBegin, inorderEnd]
这两个范围。

第二个错误,错的更深,其实到最后都没有彻底意识到,一定要当心,做此类题时。
即,我通过preorder[begin] 到inorder[]里面找到root。
然后!
root 的右边一个数字,不一定是,就是root的右结点!
我怎么错的?
我把inorder[rootIndex + 1] 在 preorder[] 数组中找了出来,把它当做是右侧子树的begin。其实不是。可能他只是右侧子树的一个节点,而真正的头结点,他并没有包含进去。
同样。root 左侧的一个数字,不一定就是root左子树的最后一个结点,不一定是end
你可以想一下,如果,左子树是一个没有右儿子的树,那么inorder 中,root左侧的一个数字,是该左子树的左儿子。但是,在preorder中,左子树的范围结束与,即end = 左子树的结点,根据访问顺序。

所以,绝对不能简单地把root左侧的数字当做左子树end,把root右侧的数字当做右子树begin。
然后就是, preorder 与 inorder 的范围不是一致的,必须要分开传入子函数,否则一定会错。

通过 postorder 与 inorder 来重构树,也是一个道理。上次做这道题目虽然很轻松地过了,但是一定是瞎猫碰到死耗子,蒙混过关。刚刚说的那些错误点,在这个类型里面同样存在!

** 这种类型的题目,最好的解法,就是算出左侧树的size,然后把它加给 preorder + leftSize 就可以得到preorder 的end。然后 这个end +1 就可以得到右侧树的preorderBegin.**

Paste_Image.png

下面在略微复习下树的遍历。

Paste_Image.png
Paste_Image.png

再推荐一个博客。
http://bangbingsyb.blogspot.com/2014/11/leetcode-construct-binary-tree-from.html

**
总结: 注意点已经在上面全部加粗表示了。
**

Anyway, Good luck, Richardo!

My code:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length == 0)
            return null;
        if (inorder == null || inorder.length == 0)
            return null;
        return helper(0, preorder.length - 1, 0, inorder.length - 1, preorder, inorder);
    }
    
    private TreeNode helper(int p1, int p2, int i1, int i2, int[] preorder, int[] inorder) {
        if (p2 <= p1) {
            return new TreeNode(preorder[p1]);
        }
        int head = preorder[p1];
        int headInorder = 0;
        for (int i = i1; i <= i2; i++) {
            if (inorder[i] == head) {
                headInorder = i;
                break;
            }
        }
        int leftNum = headInorder - i1;
        TreeNode headNode = new TreeNode(head);
        if (leftNum > 0)
            headNode.left = helper(p1 + 1, p1 + leftNum, i1, headInorder - 1, preorder, inorder);
        if (leftNum + 1 < p2 - p1 + 1)
            headNode.right = helper(p1 + leftNum + 1, p2, headInorder + 1, i2, preorder, inorder);
        return headNode;
    }
}

这次写还是比较顺利地。思路清晰的话,这道题木很简单。

Anyway, Good luck, Richardo!

My code:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length != inorder.length) {
            return null;
        }
        
        return helper(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1);
    }
    
    private TreeNode helper(int[] preorder, int[] inorder, int preLo, int preHi, int inLo, int inHi) {
        if (inLo > inHi) {
            return null;
        }
        else if (inLo == inHi) {
            return new TreeNode(inorder[inLo]);
        }
        else {
            int index = 0;
            for (int i = inLo; i <= inHi; i++) {
                if (inorder[i] == preorder[preLo]) {
                    index = i;
                    break;
                }
            }
            
            TreeNode root = new TreeNode(preorder[preLo]);
            root.left = helper(preorder, inorder, preLo + 1, preLo + index - inLo, inLo, index - 1);
            root.right = helper(preorder, inorder, preLo + index - inLo + 1, preHi, index + 1, inHi);
            return root;
        }
    }
}

想想当初刷题真的很认真。找实习的时候不该不自信的!!付出了这么多努力,就因为畏惧,都不敢投出简历!!!
最后实习找成这样,全职也受影响!不甘心!
加油。

Anyway, Good luck, Richardo! -- 08/06/2016

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

推荐阅读更多精彩内容