leetCode进阶算法题+解析(十五)

二叉树的层次遍历

题目:给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。

例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]

思路:讲真,这道题我好像也做过。记得是用了队列辅助了。其实这个用list也是可以实现的,不过队列本身先进先出,出去的时候直接弹出可以,而list就得顺序读取,读取一个删除一个。很麻烦。大概思路就是把每一层的树存进去,然后遍历,然后存值存list,本层全部取完存进结果集,同时每取一个元素要把下一层树(先左后右)再存进去。。我去代码实现了。
做完回来了,思路很清晰,我直接贴代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedBlockingQueue<TreeNode>();
        List<List<Integer>> res = new ArrayList<List<Integer>>(); 
        if(root==null) return res;
        queue.add(root);        
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList<Integer>();
            for(int i = 0;i<size;i++){
                TreeNode n = queue.poll();
                list.add(n.val);
                if(n.left!=null) queue.add(n.left);
                if(n.right!=null) queue.add(n.right);
            }
            res.add(list);
        }
        return res;
    }
}

然后我现在有点尴尬啊,,,性能只超过了百分之五,,,太打脸了,其实这个思路只要知道,还有很多数据结构能做到的,比如我 之前说的list也可以,我不知道是不是我选择的数据结构有问题,,我先试试list实现,性能还不上来我就看别人的代码了。
改成LinkedList(这个list自带removeFirst方法)性能大大的提升了,从7,8ms变成了1ms。。超过了百分之九十七的人了,我先把代码贴出来:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        LinkedList<TreeNode> d = new LinkedList<TreeNode>();
        List<List<Integer>> res = new ArrayList<List<Integer>>(); 
        if(root==null) return res;
        d.add(root);     
        while(d.size()!=0){
            int size = d.size();
            List<Integer> list = new ArrayList<Integer>();
            for(int i = 0;i<size;i++){
                TreeNode n = d.removeFirst();
                list.add(n.val);
                if(n.left!=null) d.add(n.left);
                if(n.right!=null) d.add(n.right);
            }
            res.add(list);
        }
        return res;
    }
}

顺便说一下这个LinkedList的源码,有获取第一个获取最后一个之类的,是个很方便的类,不同于ArrayList,这个是链表结构,所以获取头尾有现成的api:


提交截图

然后这道题到这我就挺满意了,这道题就到这里了,下一题。

二叉树的矩形层次遍历

题目:给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回锯齿形层次遍历如下:
[
[3],

[20,9],
[15,7]
]

思路:这道题其实就是上面那道题的演化版本,我感觉挺简单的,在while循环中创建一个计数器,单数左往右,双数右往左。闲话不说。我直接去实现了。
好了,实现完了,在做的时候有点小改动,比如计数器其实没啥必要,我换成了flag 布尔值来判断,更方便,然后true是正着添加,false是addFist也就是反着添加,我直接贴代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> res =new ArrayList<List<Integer>>();
        if(root==null) return res;
        LinkedList<TreeNode> d = new LinkedList<TreeNode>();
        d.add(root);
        boolean flag = true;
        while(d.size()!=0){
            int size = d.size();
            LinkedList<Integer> list = new LinkedList<Integer>();
            for(int i = 0;i<size;i++){
                TreeNode n = d.removeFirst();
                if(flag){
                    list.add(n.val);
                }else{
                    list.addFirst(n.val);
                }
                if(n.left!=null) d.add(n.left);
                if(n.right!=null) d.add(n.right);
            }
            flag = !flag;
            res.add(list);
        }
        return res;
    }
}

因为是在上题基础上做的,所以很容易就实现啦,性能超过百分之九十八的人,所以也不复盘了,直接pass,下一题。

从前序与中序遍历序列构造二叉树

题目:根据一棵树的前序遍历与中序遍历构造二叉树。注意:你可以假设树中没有重复的元素。

例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7

思路:这道题有点意思,一点点理思路:首先前序排列,第一个数就是根节点,然后因为题目都说了每个元素没有重复的,所以可以这么判断树结构,中序的根节点左边是左子树的,右边是右子树的。然后下一层,在左子树和右子树范围内,前序遍历中除了根节点应该顺序是左子树-右子树。上面的示例中左子树直接叶子节点了,右子树中20是第一个出现的(15,20,7中前序遍历20第一个出现),所以20是右子树的根节点,往下继续这么判断。其实就是个递归。我去尝试写一下代码。
好了,做是做出来了,我自我感觉挺好的,虽然性能贼打脸,我先贴代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length==0) return null;
        //前序第一个元素是根节点
        TreeNode res = new TreeNode(preorder[0]);
        int idx = 0;
        //找到根节点在中序遍历中的下标
        while(preorder[0]!=inorder[idx]) idx++;
        //Arrays.copyOfRange(preorder,1,idx+1),因为前序第一个是根节点,所以从第二个也就是
        //下标为1开始复制。因为含头不含尾,所以最后到idx+1
        //而中序则左右子树在跟节点两点,也就是0-idx-1个都是左子树的,所以这里直接0-idx
        res.left = buildTree(Arrays.copyOfRange(preorder,1,idx+1),Arrays.copyOfRange(inorder,0,idx));
        res.right = buildTree(Arrays.copyOfRange(preorder,idx+1,preorder.length),Arrays.copyOfRange(inorder,idx+1,inorder.length));
        return res;

    }
}

因为这个我思路也不是很顺,一直改,所以我注释写的比较清楚,就不多解释什么了。性能12ms,只超过百分之四十。。其实我能想到的就是来回来去数组copy可能是性能不好的关键。我还是直接看看性能排行第一的代码吧。

class Solution {
    private int pre=0;
    private int in=0;
    public TreeNode buildTree(int [] preorder, int [] inorder) {
        return buildTree(preorder,inorder,Integer.MAX_VALUE+1);
    }
    public TreeNode buildTree(int [] preorder,int [] inorder,long stop){
        //数组为空则返回null
        if(pre==preorder.length){
            return null;
        }
        //中序遍历序列数组顺序值等于终止值,则依次后移
        //表示此节点为空
        if(inorder[in]==stop){
            in++;
            return null;
        }
        //按照先序遍历顺序值新建节点
        int val=preorder[pre++];
        TreeNode root=new TreeNode(val);
        //建立左节点,终止值为当前节点值
        root.left=buildTree(preorder,inorder,val);
        //建立右节点,终止值为上一节点值
        root.right=buildTree(preorder,inorder,stop);
        //返回当前节点
        return root;
    }
}

瞻仰瞻仰学习学习大神代码吧。
然后今天的笔记就记到这里,如果稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利!生活健健康康!

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

推荐阅读更多精彩内容