首页 > 其他分享 >《剑指offer》day06

《剑指offer》day06

时间:2022-10-11 15:35:07浏览次数:51  
标签:TreeNode cur offer ArrayList day06 item new null

从上到下打印二叉树

题目描述

image

思路

队列

这个其实是树的基本操作之一,层序遍历,也叫广度优先遍历,可以通过队列的先进先出来实现

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    public int[] levelOrder(TreeNode root) {
        List<Integer> result=new ArrayList<Integer>();
        if (root==null){
            return new int[0];
        }
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode cur=queue.poll();
            result.add(cur.val);
            if(cur.left!=null){
                queue.offer(cur.left);
            }
            if(cur.right!=null){
                queue.offer(cur.right);
            }
        }
        int[]r=new int[result.size()];
        for(int i=0;i<r.length;i++){
            r[i]=result.get(i);
        }
        return r;
    }
}

复杂度分析

时间复杂度

O(N)

空间复杂度

O(N),首先有List,而且满二叉树的情况下,会有N/2个元素在队列里面

反思不足

java se

Queue

  • LinkedList实现了Queue接口,所以可以直接用这个类实例化

image

此外还有isEmpty用于判断是否为空,toArray返回的是Object数组,无法转化为int[]

ArrayList

image

从上到下打印二叉树II

题目描述

image

思路

双队列

将当前层与下层元素保存在两个队列中,分别出队封装

队列+size()

通过size获取当前层的个数,以之区分两层

代码实现

双队列

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    Queue<TreeNode>cur = new LinkedList<TreeNode>();
    Queue<TreeNode>next = new LinkedList<TreeNode>();
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> r = new ArrayList<List<Integer>>();
        if(root==null){
            return new ArrayList<List<Integer>>();
        }
        cur.offer(root);
        List<Integer> item = new ArrayList<Integer>();
        while(!cur.isEmpty()||!next.isEmpty()){
            
            TreeNode n=cur.poll();
            item.add(n.val);
            if(n.left!=null){
                next.offer(n.left);
            }
            if(n.right!=null){
                next.offer(n.right);
            }
            if(cur.isEmpty()){
                cur=next;
                next=new LinkedList<TreeNode>();
                r.add(item);
                item=new ArrayList<Integer>();
            }
        }
        return r;
    }
}

队列+size()

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

复杂度分析

时间复杂度

二者的本质还是层序遍历,O(N)

空间复杂度

均为O(N),但前者还是要高一点的

反思不足

思路

一开始想的是两个队列,一个存放当前层的一个存放下一层的,然后发现可行

看了题解之后,发现一个队列也可以完成,用size得到当前层的元素个数,然后设置一个for循环

我当时想的是如何能区分出两层,而没有往当前层有多少个的角度去想,也没有想过可以用这种方式区分

从上到下打印二叉树III

题目描述

image

思路

队列+栈+计数器

自己想的方法,算是学有所用

双端队列+计数器

双端队列的特点在于极端情况下两边皆可入队出队,于是就可以奇数的时候队头入队,偶数的时候队尾入队

这里的双端队列是指结果集

双端队列+奇偶判断逻辑分离

对上一种方法的优化,取消了判断当前是奇数层还是偶数层

如何分离?首先在队列中的元素都得是跟普通层序遍历一个次序,于是乎打印偶数层添加时就得从右往左加子元素,在打印奇数层时从前往后删,偶数层从后往前删,用for循环记录开始的元素个数以区分层与层

每轮都打印两层

这里的双端队列是指每层元素

队列+倒序+返回结果集size

对第一种方法的优化

用返回结果集size判断当前是奇数层还是偶数层

直接调用Collections.reverse(tmp)完成内部元素的逆置,而不用使用栈

代码实现

队列+计数器+栈

class Solution {
    Queue<TreeNode> cur = new LinkedList<TreeNode>();
    Stack<Integer> stack = new Stack<Integer>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        int cth = 1;
        List<List<Integer>> r = new ArrayList<List<Integer>>();
        if (root == null) {
            return new ArrayList<List<Integer>>();
        }
        cur.offer(root);
        List<Integer> item = new ArrayList<Integer>();

        while (!cur.isEmpty()) {
            //代码有很大程度上的冗余
            if (cth % 2 != 0) {
                for (int i = cur.size(); i > 0; i--) {
                    TreeNode n = cur.poll();
                    if (n.left != null) {
                        cur.offer(n.left);
                    }
                    if (n.right != null) {
                        cur.offer(n.right);
                    }
                    item.add(n.val);
                }
                

            }else{
                for (int i = cur.size(); i > 0; i--) {
                    TreeNode n = cur.poll();
                    if (n.left != null) {
                        cur.offer(n.left);
                    }
                    if (n.right != null) {
                        cur.offer(n.right);
                    }
                    stack.push(n.val);
                }
                while(!stack.empty()){
                    item.add(stack.pop());
                }
                
            }
            r.add(item);
            cth++;
            item = new ArrayList<Integer>();
        }
        return r;
    }
}

双端队列+计数器

class Solution {
    Queue<TreeNode> cur=new LinkedList<TreeNode>();
    public List<List<Integer>> levelOrder(TreeNode root) {
        
        List<List<Integer>> r=new ArrayList<List<Integer>>();

        if(root!=null){
            cur.offer(root);
        }
        int cth=1;
        while(!cur.isEmpty()){
            LinkedList<Integer> item=new LinkedList<Integer>();
            for(int i=cur.size();i>0;i--){
                TreeNode n=cur.poll();
                if(n.left!=null){
                    cur.offer(n.left);
                }
                if(n.right!=null){
                    cur.offer(n.right);
                }
                if(cth%2==1){
                    item.addLast(n.val);
                }else{
                    item.addFirst(n.val);
                }
            }
            r.add(item);
            cth++;
        }
        return r;
    }
}

双端队列+奇偶判断逻辑分离

class Solution {
    Deque<TreeNode> cur = new LinkedList<TreeNode>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> r = new ArrayList<List<Integer>>();
        if (root == null) {
            return new ArrayList<List<Integer>>();
        }
        cur.offer(root);
        

        while (!cur.isEmpty()) {
            //打印奇数层
                List<Integer> item = new ArrayList<Integer>();
                for (int i = cur.size(); i > 0; i--) {
                    TreeNode n = cur.removeFirst();
                    if (n.left != null) {
                        cur.addLast(n.left);
                    }
                    if (n.right != null) {
                        cur.addLast(n.right);
                    }
                    item.add(n.val);
                }
                r.add(item);
            //打印偶数层
                if(cur.isEmpty()){
                    break;
                }
                item = new ArrayList<Integer>();
                for(int i=cur.size();i>0;i--){
                    TreeNode n = cur.removeLast();
                    if (n.right != null) {
                        cur.addFirst(n.right);
                    }
                    if (n.left != null) {
                        cur.addFirst(n.left);
                    }
                    item.add(n.val);
                }
                r.add(item);
                
        }
        return r;
    }
}

队列+倒序+返回结果集size

class Solution {
    Queue<TreeNode> cur = new LinkedList<TreeNode>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        int cth = 1;
        List<List<Integer>> r = new ArrayList<List<Integer>>();
        if (root == null) {
            return new ArrayList<List<Integer>>();
        }
        cur.offer(root);
        List<Integer> item = new ArrayList<Integer>();

        while (!cur.isEmpty()) {
            //代码有很大程度上的冗余
                for (int i = cur.size(); i > 0; i--) {
                    TreeNode n = cur.poll();
                    if (n.left != null) {
                        cur.offer(n.left);
                    }
                    if (n.right != null) {
                        cur.offer(n.right);
                    }
                    item.add(n.val);
                }
                if(r.size()%2==1){
                    Collections.reverse(item);
                }
            r.add(item);
            cth++;
            item = new ArrayList<Integer>();
        }
        return r;
    }
}

复杂度分析

时间复杂度

均为O(N)

空间复杂度

均为O(N)

反思不足

思路

在上一题的基础上,想到用计数器加栈的方式实现,可行,而且效率不错

该思路的代码可以优化,冗余太多

优化方法就是利用双端队列

java se

Collections

有关api:

  • Collections.reverse(tmp)可完成对内部元素的逆置

Deque

双端队列所实现的接口

有关api:

  • addFirst

  • addLast

  • removeFirst

  • removeLast

LinkedList

该类可做双端队列使用

标签:TreeNode,cur,offer,ArrayList,day06,item,new,null
From: https://www.cnblogs.com/zhouj-learn/p/16779384.html

相关文章

  • 《剑指offer》day03
    替换空格题目描述思路原地修改适用于c++这种字符串可变的语言,可以直接使用双指针法双指针法先将原空间扩容至结果所需大小,然后两个指针分别指向旧的和新的的尾部......
  • 《剑指offer》day02
    从尾到头打印链表题目要求思路逆置法由于要求以数组的形式返回,所以没法节省空间,没有此限制的话该方法的空间复杂度可达到O(1),将链表逆置再打印即可辅助栈法利用......
  • 剑指Offer-55-二叉树的深度/力扣-104-二叉树的最大深度
    intmaxDepth(TreeNode*root){ if(!root)return0; intleft=maxDepth(root->left); intright=maxDepth(root->right); //返回二叉树的深度 //只要......
  • 剑指 Offer 03. 数组中重复的数字
    力扣链接:剑指Offer03.数组中重复的数字acwing链接最初的思路是,将所有数据放入桶中,数据存在,数据桶值就++,有数据重复就retrunnums[i],无数据重复就return-1,且需......
  • 《剑指offer》day01
    用两个栈实现队列题目要求思路栈的特性是先进后出,而队列的特性是先进先出,用栈实现队列的话就需要一个辅助栈来逆置原来的栈序列。代码classCQueue{Stack<I......
  • LeetCode(剑指 Offer)- 61. 扑克牌中的顺子
    题目链接:​​点击打开链接​​题目大意:略解题思路相关企业字节跳动AC代码Java//解决方案(1)classSolution{publicbooleanisStraight(int[]nums){Set<In......
  • day06-多表查询02
    多表查询024.表复制自我复制数据(蠕虫复制)有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以用此法为表创建海量数据--为了对某个sql语句进行效率测试,我们需......
  • 剑☞offer 两个链表的第一个公共节点
    题目描述:给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。题目数据 保证 整个链式结构中不存......
  • 力扣剑指offer——二叉树篇
    ✔✨前言......
  • java_day06
    Java流程控制循环结构增强for循环Java5引入了一种主要用于数组或集合的增强型for循环增强型for循环格式如下:for(声明语句:表达式){//代码}声明语......