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

LeetCode题目:

  • [654. 最大二叉树](#654. 最大二叉树)
  • [617. 合并二叉树](#617. 合并二叉树)
  • [700. 二叉搜索树中的搜索](#700. 二叉搜索树中的搜索)
  • [98. 验证二叉搜索树](#98. 验证二叉搜索树)
  • [2843. 统计对称整数的数目](#2843. 统计对称整数的数目)

其他:

今日总结
往期打卡


654. 最大二叉树

跳转:
学习: 代码随想录公开讲解

问题:

给定一个不重复的整数数组 nums最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的 *最大二叉树*

思路:

这道题要求构造二叉树,使用前序遍历先构造自身再构造子树比较符合直觉,当然,先构造子节点再构造父节点后序遍历也是没有问题的,不过需要先存储子节点再构造父节点,比较麻烦.当然,用中序遍历也是,只需要先处理到左根,再创建节点,再绑定右子树即可.所以说前中后序只是创建节点的位置不同.

但这题用层序遍历就不是很合适,因为数组不是很好划分,要存储全部路径的边界状态.

因为需要获取两个子节点再操作本节点,所以使用迭代法比较麻烦.

复杂度:

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

代码(前序递归实现):

java 复制代码
class Solution {
    TreeNode getTree(int[] nums,int l,int r)
    {
        if(l>=r) return null;
        if(r-l==1) return new TreeNode(nums[l]);
        int index = l;
        int max = 0;
        for(int i=l;i<r;i++){
            if(nums[i]>max){
                max = nums[i];
                index = i;
            }
        }
        TreeNode root = new TreeNode(max);
        root.left = getTree(nums,l,index);
        root.right = getTree(nums,index+1,r);
        return root;
    }
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return getTree(nums,0,nums.length);
    }
}

617. 合并二叉树

跳转:
学习: 代码随想录公开讲解

问题:

给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

思路:

两棵树一起遍历,如果都不为null就合并,一方为null就返回另一方.

这里直接前序遍历

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( l o g n ) O(logn) O(logn)

代码:

java 复制代码
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if(root1==null) return root2;
        if(root2==null) return root1;
        TreeNode root = new TreeNode(root1.val+root2.val);
        root.left = mergeTrees(root1.left,root2.left);
        root.right = mergeTrees(root1.right,root2.right);
        return root;
    }
}

700. 二叉搜索树中的搜索

跳转:
学习: 代码随想录公开讲解

问题:

给定二叉搜索树(BST)的根节点 root 和一个整数值 val

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null

思路:

这里直接利用二叉搜索树的性质选择递归方向即可

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( l o g n ) O(logn) O(logn)

代码:

java 复制代码
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if(root==null) return null;
        if(root.val==val) return root;
        if(root.val>val) return searchBST(root.left,val);
        return searchBST(root.right,val);
    }
}

98. 验证二叉搜索树

跳转:
学习: 代码随想录公开讲解

问题:

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

思路:

右子树中所有节点都大于当前节点,左子树中所有节点都小于当前节点,基于此,可以使用边界收缩法,判断子节点是否在边界内

当然,二叉搜索树有一个很重要的性质,那就是中序遍历下单调递增.所以如果能想到这条性质可以降低编码复杂度,并提升代码效率.

复杂度:

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

代码(中序遍历):

java 复制代码
class Solution {
    long pre = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if(root==null) return true;
        if(!isValidBST(root.left)) return false;
        if(root.val<=pre) return false;
        pre = root.val;
        return isValidBST(root.right);
    }
}

代码(边界收缩):

java 复制代码
class Solution {
    boolean handle(TreeNode root,long lBorder,long rBorder){
        if (root == null)
            return true;
        boolean a, b;
        a = true;
        b = true;
        if (root.left != null)
            if (root.left.val>lBorder&&root.left.val<root.val)
                a = handle(root.left,lBorder,root.val);
            else
                return false;
        if (root.right != null)
            if (root.right.val>root.val&&root.right.val<rBorder)
                b = handle(root.right,root.val,rBorder);
            else
                return false;

        return a&b;
    }
    public boolean isValidBST(TreeNode root) {
        return handle(root,Long.MIN_VALUE,Long.MAX_VALUE);
    }
}

2843. 统计对称整数的数目

跳转:

问题

给你两个正整数 lowhigh

对于一个由 2 * n 位数字组成的整数 x ,如果其前 n 位数字之和与后 n 位数字之和相等,则认为这个数字是一个对称整数。

返回在 [low, high] 范围内的 对称整数的数目

思路:

找特殊数,最简单的方法就是把所有可能用到的特殊数都记下来,然后枚举特殊数进行判断.当然范围较小的情况下遍历范围里的数其实也差不多

当然,也可以直接枚举每位判断

复杂度:

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

代码(哈希字典1):

java 复制代码
class Solution {
    public int countSymmetricIntegers(int low, int high) {
        int[] hash = new int[1000];
        int l = 0;
        for(int i=1;i<10;i++){
            hash[l++] = i+10*i; 
        }
        for(int i=1;i<10;i++){
            for(int j=0;j<10;j++){
                for(int k=0;k<10&&k<=i+j;k++){
                    if(i+j-k>=10) continue;
                    hash[l++]=(i*1000+j*100+k*10+(i+j-k));
                }
            }
        }
        int ans = 0;
        for(int i:hash){
            if(i<low) continue;
            if(i>high||i==0) break;
            ans++;
        }
        return ans;
    }
}

代码(哈希字典2):

java 复制代码
class Solution {
    public int countSymmetricIntegers(int low, int high) {
        int[] hash = new int[10001];
        for(int i=1;i<10;i++){
            hash[i+10*i]++; 
        }
        for(int i=1;i<10;i++){
            for(int j=0;j<10;j++){
                for(int k=0;k<10&&k<=i+j;k++){
                    if(i+j-k>=10) continue;
                    hash[(i*1000+j*100+k*10+(i+j-k))]++;
                }
            }
        }
        int ans = 0;
        for(int i = low;i<=high;i++){
            if(hash[i]==1) ans++;
        }
        return ans;
    }
}

总结

今天主要是复习了二叉搜索树相关的概念.

往期打卡

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

*[617. 合并二叉树]: LeetCode
*[700. 二叉搜索树中的搜索]: LeetCode
*[98. 验证二叉搜索树]: LeetCode
*[654. 最大二叉树]: LeetCode
*[2843. 统计对称整数的数目]: LeetCode

相关推荐
梭七y30 分钟前
【力扣hot100题】(089)最长有效括号
算法·leetcode·职场和发展
珂朵莉MM1 小时前
2025第四届大学生算法挑战赛 赛前测试赛 题解
算法
LabVIEW开发1 小时前
LabVIEW 图像处理中常见的边缘检测算法
图像处理·算法·labview
nuo5342022 小时前
第十六届蓝桥杯 省赛C/C++ 大学B组
c语言·c++·算法·蓝桥杯·图论
dokii12 小时前
leetcode572 另一棵树的子树
java·开发语言·算法
无敌的牛2 小时前
双数之和+三数之和+四数之和
数据结构·算法
tpoog2 小时前
[MySQL] 表的增删查改(查询是重点)
linux·数据库·mysql·算法·贪心算法
一只拉古3 小时前
掌握贪心(Greedy)算法:从 LeetCode 难题到系统架构
算法·leetcode·面试
xrkhy3 小时前
提高课:数据结构之树状数组
数据结构·c++·算法