代码随想录第十五天|层序遍历、翻转二叉树、对称二叉树

Leetcode 102. 二叉树的层序遍历

题目链接: 二叉树的层序遍历
自己的思路:层序遍历的标准模板,其他的基本上都是在上面进行改动;基本思想就是用队列来存储每一层数的结点。

正确思路:队列。

代码:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        Queue<TreeNode> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){
            //记录当前队列中结点数量
            int size = qe.size();
            //存储每一层的数据
            List<Integer> temp = new ArrayList<>();
            while(size--!=0){
                TreeNode node = qe.peek();
                temp.add(node.val);
                qe.poll();
                //从左到右加入到队列中
                if (node.left!=null)  qe.add(node.left);
                if (node.right!=null)  qe.add(node.right);
            }
            res.add(temp);
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

相似题型

Leetcode 107. 二叉树的层序遍历 II

题目链接: 二叉树的层序遍历 II
自己的思路:在模板的基础上增加了反转集合这一操作!

代码:

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        Queue<TreeNode> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){
            int size = qe.size();
            List<Integer> temp = new ArrayList<>();
            while(size--!=0){
                TreeNode node = qe.peek();
                qe.poll();
                temp.add(node.val);
                if (node.left!=null) qe.add(node.left);
                if (node.right!=null) qe.add(node.right); 
            }
            res.add(temp);
        }
        Collections.reverse(res);
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 199. 二叉树的右视图

题目链接: 二叉树的右视图
自己的思路:在模版的基础上加了一个判断条件:if(size==0)就把数据加入到res中,因为是右视图,所以只需要把最右边的数据加入到数组里即可。

代码:

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Queue<TreeNode> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){
            int size = qe.size();
            while(size--!=0){
                TreeNode node = qe.peek();
                qe.poll();
                if (size==0) res.add(node.val);
                if (node.left!=null) qe.add(node.left);
                if (node.right!=null) qe.add(node.right);
            }
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 637. 二叉树的层平均值

题目链接: 二叉树的层平均值
自己的思路:在模板的基础上加了一个求和除以队列长度的过程!

代码:

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new ArrayList<>();
        Queue<TreeNode> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){
            int size = qe.size();
            int temp = size;
            double sum = 0.0;
            while(size--!=0){
                TreeNode node = qe.peek();
                qe.poll();
                sum += node.val;
                if (node.left!=null)  qe.add(node.left);
                if (node.right!=null) qe.add(node.right);
            }
            res.add(sum/temp);
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 429. N 叉树的层序遍历

题目链接: 叉树的层序遍历
自己的思路:在模板的基础上加个了多叉树,原理都一样,加一个for循环即可!

代码:

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new ArrayList<>();
        Queue<Node> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){
            int size = qe.size();
            List<Integer> temp = new ArrayList<>();
            while(size--!=0){
                Node node = qe.peek();
                qe.poll();
                temp.add(node.val);
                List<Node> children = node.children;
                for (Node cnode:children){
                    if (cnode!=null) qe.add(cnode);
                }
            }
            res.add(temp);
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 515. 在每个树行中找最大值

题目链接: 在每个树行中找最大值
自己的思路:在模板的基础上每一层定义一个临时变量保存最大值,然后加入到数组中!!

代码:

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Queue<TreeNode> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){
            int size = qe.size();
            //定义临时变量保存最大值
            int temp = Integer.MIN_VALUE;
            while(size--!=0){
                TreeNode node = qe.peek();
                qe.poll();
                temp = Math.max(temp,node.val);
                if (node.left!=null) qe.add(node.left);
                if (node.right!=null) qe.add(node.right);
            }
            res.add(temp);
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 116. 填充每个节点的下一个右侧节点指针

题目链接: 填充每个节点的下一个右侧节点指针
自己的思路:没想出来!!!
代码:

class Solution {
    public Node connect(Node root) {
        LinkedList<Node> qe = new LinkedList<>();
        if (root!=null) qe.add(root);
        while(!qe.isEmpty()){

            //连接每一层的结点
            int size = qe.size();
            Node temp = qe.peek();
            for (int i =1;i<size;i++){
                temp.next = qe.get(i);
                temp = qe.get(i);
            }
            while(size--!=0){
                Node node = qe.peek();
                qe.poll();
                if (node.left!=null) qe.add(node.left);
                if (node.right!=null) qe.add(node.right);
            }

        }
        return root;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

上面的代码不满足常量级的空间复杂度,直接舍弃!!

代码:空间复杂度为1!!

class Solution {
	public Node connect(Node root) {
		if(root==null) {
			return root;
		}
		Node pre = root;
		//循环条件是当前节点的left不为空,当只有根节点
		//或所有叶子节点都出串联完后循环就退出了
		while(pre.left!=null) {
			Node tmp = pre;
			while(tmp!=null) {
				//将tmp的左右节点都串联起来
				tmp.left.next = tmp.right;
				//下一个不为空说明上一层已经帮我们完成串联了
				//连接下一层非同一根节点的Node
				if(tmp.next!=null) {
					tmp.right.next = tmp.next.left;
				}
				//继续右边遍历
				tmp = tmp.next;
			}
			//从下一层的最左边开始遍历
			pre = pre.left;
		}
		return root;
	}
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)

代码:递归!!!!

class Solution {
    public Node connect(Node root) {
        dfs(root);
        return root;
    }

    public void dfs(Node node){
        if (node==null) return;
        Node left = node.left;
        Node right = node.right;
        while(left!=null){
            left.next = right;
            left = left.right;
            right = right.left;
        }
        dfs(node.left);
        dfs(node.right);
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( h ) \mathcal{O}(h) O(h) h h h为树的深度

Leetcode 117. 填充每个节点的下一个右侧节点指针 II

题目链接: 填充每个节点的下一个右侧节点指针 II

正确思路:和116题有点类似,层序遍历的话可以直接照搬过来,但是第二种方法不可以,要进行一些改动,这里我们选择使用类似链表的方法将每一层连接起来!!!
代码:

class Solution {
    public Node connect(Node root) {
        if (root==null) return root;
        Node pre = root;
        while(pre!=null){
            //定义一个虚拟节点来表示下一层第一个结点
            Node dummy = new Node(0);
            Node temp = dummy;
            while(pre!=null){
                //连接下一层
                if (pre.left!=null){
                    temp.next = pre.left;
                    temp = temp.next;
                }
                if (pre.right!=null){
                    temp.next = pre.right;
                    temp = temp.next;
                }
                //当前层向右走,连接下一层
                pre = pre.next;
            }
            //开始连接下一层的下一层
            pre = dummy.next;
        }
        return root;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)

Leetcode 104. 二叉树的最大深度

题目链接: 二叉树的最大深度
自己的思路:在模板的基础上每遍历一层给res+1即可!!!

代码:

class Solution {
    public int maxDepth(TreeNode root) {
        int res = 0;
        LinkedList<TreeNode> queue = new LinkedList<>();
        if (root!=null) queue.add(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size--!=0){
                TreeNode node = queue.poll();
                if (node.left!=null) queue.add(node.left);
                if (node.right!=null) queue.add(node.right);
            }
            res++;
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 111. 二叉树的最小深度

题目链接: 二叉树的最小深度
自己的思路:在模板的基础上加一个判断,如果当前节点的左右节点都为空,则说明到达最低点,返回最小深度即可!!

代码:

class Solution {
    public int minDepth(TreeNode root) {
        int res = 0;
        LinkedList<TreeNode> queue = new LinkedList<>();
        if (root!=null) queue.add(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            res++;
            while(size--!=0){
                TreeNode node = queue.poll();
                if (node.left!=null) queue.add(node.left);
                if (node.right!=null) queue.add(node.right);
                //当左右结点都为空的时候,说明遍历到了最低点,直接返回即可
                if (node.left==null&&node.right==null) return res;
            }
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 226. 翻转二叉树

题目链接: 翻转二叉树
自己的思路:没想到!!!

正确思路:假设当前结点为node,先交换左右结点,然后再递归交换下面的结点即可!!!不要想递归的本质!!!!没用!!!!!

递归代码:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        //终止条件,当碰到空指针的时候结束递归
        if (root==null) return root;
        //交换两个节点
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        //然后再递归交换下面每个节点
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

层序遍历代码:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root==null) return root;
        LinkedList<TreeNode> queue = new LinkedList<>();
        if (root!=null) queue.add(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size--!=0){
                TreeNode node = queue.poll();
                //交换当前结点的左右结点
                TreeNode temp = node.left;
                node.left = node.right;
                node.right = temp;
                if (node.left!=null) queue.add(node.left);
                if (node.right!=null) queue.add(node.right);
            }
        }
        return root;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 101. 对称二叉树

题目链接: 对称二叉树
自己的思路:没想到,递归方法一直做不好!!!多练!!!

递归正确思路:主要在于终止条件的判断以及单层递归的逻辑,终止条件就是除了两个结点的值相等之外的情况,因为如果两个结点的值相等的话,还需要继续向下递归比较下面的结点是否对称,其他情况直接就可以返回值,在进行单层递归的时候,一定要注意输入参数的顺序!!!

代码:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return recur(root.left,root.right);
    }

    public boolean recur(TreeNode left,TreeNode right){
        //终止条件
        if (left==null&&right!=null) return false;
        else if (left!=null&&right==null) return false;
        else if (left==null&&right==null) return true;
        else if (left.val!=right.val) return false;
        //当两个节点的值相等时,继续向下递归判断下面的子树是否是对称的
        return recur(left.left,right.right)&&recur(left.right,right.left);
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)

层序遍历正确思路:主要思想是加入到队列中的二叉树节点的顺序,要按照需要比较的结点的顺序来,这样对队列进行poll的时候,可以正确的比较!!
代码:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root==null) return true;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root.left);
        queue.add(root.right);
        while(!queue.isEmpty()){
            //需要比较的两个二叉树结点
            TreeNode lnode = queue.poll();
            TreeNode rnode = queue.poll();
            //跳出当前循环的条件
            if (lnode==null&&rnode==null) continue;
            if (lnode==null||rnode==null) return false;
            if (lnode.val!=rnode.val) return false;
            //注意加入的顺序即是比较的顺序
            queue.add(lnode.left);
            queue.add(rnode.right);
            queue.add(lnode.right);
            queue.add(rnode.left);
        }
        return true;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值