当前位置: 首页 > news >正文

代码随想录算法训练营第十二天

LeetCode题目:

  • 226. 翻转二叉树
  • 101. 对称二叉树
  • 104. 二叉树的最大深度
  • 111. 二叉树的最小深度
  • 3396. 使数组元素互不相同所需的最少操作次数(每日一题)

其他:

今日总结
往期打卡


226. 翻转二叉树

跳转: 226. 翻转二叉树

问题:

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

提示:

  • 树中节点数目范围在 [0, 100]
  • -100 <= Node.val <= 100

在这里插入图片描述

思路:

自底向上每个节点交换左右节点即可,所以可以后序遍历做子树交换

当然前序遍历,层序遍历都是没有什么问题的

但如果中序遍历,因为交换前已经遍历了一棵子数,交换后还要沿着遍历过的方向遍历子树,所以编码实现上稍微有些不同

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码(后序遍历):

class Solution {
    void reverse(TreeNode root) {
        if (root == null) return;
        reverse(root.left);
        reverse(root.right);
        swap(root);
    }
    void swap(TreeNode root){
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }

    public TreeNode invertTree(TreeNode root) {
        reverse(root);
        return root;
    }
}

代码(前序遍历):

class Solution {
    void reverse(TreeNode root) {
        if (root == null) return;
        swap(root);
        reverse(root.left);
        reverse(root.right);
    }
    void swap(TreeNode root){
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }

    public TreeNode invertTree(TreeNode root) {
        reverse(root);
        return root;
    }
}

代码(中序遍历):

class Solution {
    void reverse(TreeNode root) {
        if (root == null) return;
        reverse(root.left);
        swap(root);
        reverse(root.left);
    }
    void swap(TreeNode root){
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }

    public TreeNode invertTree(TreeNode root) {
        reverse(root);
        return root;
    }
}

代码(层序遍历):

class Solution {
    void swap(TreeNode root){
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }

    public TreeNode invertTree(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i=0;i<size;i++){
                TreeNode tmp = queue.poll();
                if(tmp==null) continue;
                swap(tmp);
                queue.add(tmp.left);
                queue.add(tmp.right);
            }
        }
        return root;
    }
}

101. 对称二叉树

跳转: 101. 对称二叉树

问题:

给你一个二叉树的根节点 root , 检查它是否轴对称。

在这里插入图片描述

提示:

  • 树中节点数目在范围 [1, 1000]
  • -100 <= Node.val <= 100

思路:

可以看作比较左右两棵子树,判断是否一二叉树左子树等于另一二叉树右子树.

所以只需要反着比较就可以了,这里使用前序遍历和层序遍历,可以在发现不相等时即返回,不必等待遍历完成.

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码(递归):

class Solution {
    boolean compare(TreeNode tree1,TreeNode tree2){
        if(tree1==null&&tree2==null){
            return true;
        }
        if(tree1==null||tree2==null) return false;
        if(tree1.val!=tree2.val) return false;
        boolean a = compare(tree1.left,tree2.right);
        boolean b = compare(tree1.right,tree2.left);
        return a&b;
    }
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return compare(root.left , root.right);
    }
}

代码(迭代):

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null) return true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root.left);
        queue.add(root.right);
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i=0;i<size;i+=2){
                TreeNode a = queue.poll();
                TreeNode b = queue.poll();
                if(a==null&&b==null) continue;
                if(a==null||b==null) return false;
                if(a.val!=b.val) return false;
                queue.add(a.left);
                queue.add(b.right);
                queue.add(a.right);
                queue.add(b.left);
            }
        }
        return true;
    }
}

104. 二叉树的最大深度

跳转: 104. 二叉树的最大深度

问题:

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

提示:

  • 树中节点的数量在 [0, 104] 区间内。
  • -100 <= Node.val <= 100

在这里插入图片描述

思路:

遍历一遍,到null记录一下深度,最大值就是最大深度
怎么遍历都可以,这里使用递归遍历(因为不用处理节点信息,所以不必区分前中后序,可以看作深搜)

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码(递归遍历):

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

111. 二叉树的最小深度

跳转: 111. 二叉树的最小深度

问题:

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

**说明:**叶子节点是指没有子节点的节点。

提示:

  • 树中节点数的范围在 [0, 105]
  • -1000 <= Node.val <= 1000

在这里插入图片描述

思路:

最小遍历需要注意找最上层的叶子节点,如果要保持判断条件为null返回,就要进一步分类处理

当然一遍遍历肯定是可以解决的
这道题比较适合使用层序遍历

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码(递归遍历):

class Solution {
    int getMinDeep(TreeNode root){
        if(root==null){
            return 0;
        }
        int leftDepth = getMinDeep(root.left)+1;
        int rightDepth = getMinDeep(root.right)+1;
        if(root.left==null) return rightDepth;
        if(root.right==null) return leftDepth;
        return Math.min(rightDepth,leftDepth);
    }
    public int minDepth(TreeNode root) {
        return getMinDeep(root);
    }
}

代码(层序遍历):

class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        int depth = 0;
        while(!queue.isEmpty()){
            int size = queue.size();
            depth++;
            for(int i=0;i<size;i++){
                TreeNode tmp = queue.poll();
                if(tmp==null) continue;
                if(tmp.left==null&&tmp.right==null) return depth;
                queue.add(tmp.left);
                queue.add(tmp.right);
            }
        }
        return depth;
    }
}

3396. 使数组元素互不相同所需的最少操作次数(每日一题)

跳转: 3396. 使数组元素互不相同所需的最少操作次数

问题

给你一个整数数组 nums,你需要确保数组中的元素 互不相同 。为此,你可以执行以下操作任意次:

  • 从数组的开头移除 3 个元素。如果数组中元素少于 3 个,则移除所有剩余元素。

注意: 空数组也视作为数组元素互不相同。返回使数组元素互不相同所需的 最少操作次数
提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100

在这里插入图片描述

思路:

可以双指针+哈希(如果数字范围再大些有负数也可以用Map存偏移)
这个思路是用慢指针存储维持哈希各值唯一的最小开头位置

当然,因为题目是只能从开头操作,所以逆序遍历的思路更好

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

代码(逆序遍历+哈希):

class Solution {
    public int minimumOperations(int[] nums) {
        int n = nums.length;
        int[] hash = new int[101];
        while(n-->0){
            int tmp = nums[n];
            if(hash[tmp]>0) return n/3+1;
            hash[tmp]++;
        }
        return 0;
    }
}

代码(双指针+哈希):

class Solution {
    public int minimumOperations(int[] nums) {
        int n = nums.length;
        int[] hash = new int[101];
        while(n-->0){
            int tmp = nums[n];
            if(hash[tmp]>0) return n/3+1;
            hash[tmp]++;
        }
        return 0;
    }
}

总结

今天主要应用了一下二叉树的四种遍历方式,然后从每日一题中复习了一下哈希.

往期打卡

代码随想录算法训练营第一天

代码随想录算法训练营第二天

代码随想录算法训练营第三天

代码随想录算法训练营第四天

代码随想录算法训练营周末一

代码随想录算法训练营第五天

代码随想录算法训练营第六天

代码随想录算法训练营第七天

代码随想录算法训练营第八天

代码随想录算法训练营第九天

代码随想录算法训练营第十天

代码随想录算法训练营周末二

代码随想录算法训练营第十一天

相关文章:

  • 【ES系列】Elasticsearch从入门到精通保姆级教程 | 启篇
  • Java9新特性
  • Python 并发编程指南:协程 vs 多线程及其他模型比较
  • SpringBoot集成RedisSearch
  • 深度学习|注意力机制
  • 【Java中级】11章、注解、元注解介绍、快速入门,了解java注解的基本使用方式【2】
  • vscode 跳转失败之c_cpp_properties.json解析
  • 【从一个 TypeScript 报错理解 ES6 模块的三种导入方式】
  • 北京自在科技:让万物接入苹果Find My网络的″钥匙匠″
  • sql-labs靶场 less-2
  • PyTorch张量范数计算终极指南:从基础到高阶实战
  • Python: sqlite3.OperationalError: no such table: ***解析
  • 在1panel中安装WebUI
  • 未来杭州:科技与诗意的时空交响曲
  • Linux 学习笔记(4):cd 与 pwd 命令的深度解析与实战应用(期末、期中复习必备)
  • ArcGis Reclassify CDL
  • muduo:运行起来
  • Prometheus采集容器故障排查
  • 从CAD数据到智能计量:Inspire如何借助HOOPS SDK创计量新高度
  • 【C++11】特殊类的设计 单例模式 类型转换