算法打卡day17|二叉树篇06|Leetcode 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

算法题

Leetcode  654.最大二叉树

题目链接:654.最大二叉树

大佬视频讲解:最大二叉树视频讲解

个人思路

大概思路就是在数组中 找最大值的节点作为当前节点,用最大值的index切割左右子树的区间,往复循环到数组元素为0;

解法

递归法

按照思路来看递归法是不错的选择;可以采用前序遍历,因为是先构造中间节点,然后递归构造左子树和右子树

 1.确定递归函数的参数和返回值参数

传入的是存放元素的数组返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。

2.确定终止条件

题目中说了输入的数组大小一定是大于等于1的,所以不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。

那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。

 3.确定单层递归的逻辑

 1.先要找到数组中最大的值和对应的下标最大的值构造根节点,下标用来下一步分割数组

 2.最大值所在的下标左区间 构造左子树

这里要判断maxValueIndex > 0,因为要保证左区间至少有一个数值

 3.最大值所在的下标右区间 构造右子树

判断maxValueIndex < (nums.size() - 1),确保右区间至少有一个数值

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return constructMaximumBinaryTree1(nums, 0, nums.length);
    }

    public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
        if (rightIndex - leftIndex < 1) {// 遍历完数组时返回空
            return null;
        }

        if (rightIndex - leftIndex == 1) {// 只有一个元素
            return new TreeNode(nums[leftIndex]);
        }

        int maxIndex = leftIndex;// 最大值所在位置
        int maxVal = nums[maxIndex];// 最大值
        for (int i = leftIndex + 1; i < rightIndex; i++) {//遍历找最大值和节点位置
            if (nums[i] > maxVal){
                maxVal = nums[i];
                maxIndex = i;
            }
        }

        TreeNode root = new TreeNode(maxVal);//最大值作为当前节点

        // 根据maxIndex划分左右子树
        root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
        root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);

        return root;
    }
}

时间复杂度:O(n);(遍历整棵树,每个元素最多被访问一次)

空间复杂度:O(n);(递归树的高度h)


Leetcode 617.合并二叉树

题目链接:617.合并二叉树

大佬视频讲解:合并二叉树视频讲解

个人思路

这个和构造一颗二叉树差不多,只是需要同时操控两棵树,所以只用同时遍历两棵二叉树,把树A和树B的节点值相加到树A,最后返回树A即可;

解法
递归法

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null) return root2;//2.确定终止条件
        if (root2 == null) return root1;
        
        //3.确定单层递归的逻辑
        root1.val += root2.val;//两颗数节点值相加

        root1.left = mergeTrees(root1.left,root2.left);//左树合并
        root1.right = mergeTrees(root1.right,root2.right);//右树合并

        return root1;//1.确定递归函数的参数和返回类型
    }
}

时间复杂度:O(n);(最差遍历一遍树)

空间复杂度:O(n);(递归树的高度h)

迭代法

也可以用队列,模拟的层序遍历,同时遍历,将值加到一棵树上,最后返回这棵树;

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null) return root2;
        if (root2 ==null) return root1;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root1);
        queue.offer(root2);

        while (!queue.isEmpty()) {
            TreeNode node1 = queue.poll();
            TreeNode node2 = queue.poll();
            // 此时两个节点一定不为空,val相加
            node1.val = node1.val + node2.val;

            // 如果两棵树左节点都不为空,加入队列
            if (node1.left != null && node2.left != null) {
                queue.offer(node1.left);
                queue.offer(node2.left);
            }
            // 如果两棵树右节点都不为空,加入队列
            if (node1.right != null && node2.right != null) {
                queue.offer(node1.right);
                queue.offer(node2.right);
            }

            // 若node1的左节点为空,直接赋值
            if (node1.left == null && node2.left != null) {
                node1.left = node2.left;
            }
            // 若node1的右节点为空,直接赋值
            if (node1.right == null && node2.right != null) {
                node1.right = node2.right;
            }

        }
        return root1;
    }
}

时间复杂度:O(n);(遍历2棵树)

空间复杂度:O(n);(使用两个队列)


Leetcode 700.二叉搜索树中的搜索

题目链接:700.二叉搜索树中的搜索

 大佬视频讲解:二叉搜索树中的搜索视频讲解

个人思路

对于普通二叉树和搜素树都能递归法,一层层找,找到节点值与目标值相同时,返回该节点。

解法

回顾一下二叉搜索树,它是一个有序树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树

递归法

可以根据二叉搜索树的特性(left<root, right>root),优化一下递归

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val) {//终止条件
            return root;//返回参数
        }
        //递归逻辑
        if (val < root.val) {
            return searchBST(root.left, val);//往左搜索
        } else {
            return searchBST(root.right, val);//往右搜索
        }
    }
}

递归搜索普通二叉树的代码如下:

class Solution {
    // 递归,普通二叉树
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }
        TreeNode left = searchBST(root.left, val);
        if (left != null) {
            return left;
        }
        return searchBST(root.right, val);
    }
}

时间复杂度:O(n);(最差遍历一遍树)

空间复杂度:O(n);(递归树的高度h)

迭代法

因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。

对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。而对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。

例如要搜索元素为11的节点,不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。中间节点如果大于11就向左走,如果小于11就向右走,如图:

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        //不用栈也能模拟递归
        while (root != null)
            if (val < root.val) root = root.left;
            else if (val > root.val) root = root.right;
            else return root;

        return null;
    }
}

时间复杂度:O(n);(遍历整棵树)

空间复杂度:O(1);(没有使用其他辅助空间)

迭代搜索普通二叉树代码如下:

class Solution {
    // 迭代,普通二叉树
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            TreeNode pop = stack.pop();
            if (pop.val == val) {
                return pop;
            }
            if (pop.right != null) {
                stack.push(pop.right);
            }
            if (pop.left != null) {
                stack.push(pop.left);
            }
        }

        return null;
    }
}

时间复杂度:O(n);(遍历整棵树)

空间复杂度:O(n);(使用栈模拟递归)


Leetcode 98.验证二叉搜索树

题目链接:98.验证二叉搜索树

大佬视频讲解:验证二叉搜索树视频讲解

个人思路

刚刚做完搜索树,但如何验证搜索树的思路却不清晰...

解法
递归法

首先这道题目比较容易犯个错误:

不能单纯的比较左节点小于中间节点,右节点大于中间节点

因为搜索树要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点

例如: [10,5,15,null,null,6,20] 这个case:

节点10大于左节点5,小于右节点15,但右子树里出现了一个6 这就不符合了!

然后继续递归三步走,这里采用中序遍历,因为要先知道根节点的值,再去比较左右子节点:

1.确定递归函数,返回值以及参数

如果没有找到这个节点就遍历了整个树,如果找到不符合的节点了,立刻返回。

2.确定终止条件

如果是空节点 也是二叉搜索树

3.确定单层递归的逻辑

中序遍历,一直更新maxVal,一旦发现maxVal >= root->val,就返回false,注意元素相同时候也要返回false。

class Solution {
    TreeNode max;
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        // 左
        boolean left = isValidBST(root.left);
        if (!left) {
            return false;
        }
        // 中
        if (max != null && root.val <= max.val) {
            return false;
        }
        max = root;
        // 右
        boolean right = isValidBST(root.right);
        return right;
    }
}

时间复杂度:O(n);(遍历二叉树)

空间复杂度:O(n);(递归树的高度h)

迭代法

可以用栈模拟递归中序遍历;

class Solution {  
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;// 左
            }
            // 中,处理节点,判断大小
            TreeNode pop = stack.pop();
            if (pre != null && pop.val <= pre.val) {
                return false;
            }
            pre = pop;

            root = pop.right;// 右
        }
        return true;
    }
}

时间复杂度:O(n);(遍历二叉树)

空间复杂度:O(n);(模拟递归的栈)


以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/458764.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】二叉搜索树底层刨析

文章目录 1. 二叉搜索树的实现2. 二叉搜索树的应用3. 改造二叉搜索树为 KV 结构4. 二叉搜索树的性能分析 1. 二叉搜索树的实现 namespace key {template<class K>struct BSTreeNode{typedef BSTreeNode<K> Node;Node* _left;Node* _right;K _key;BSTreeNode(const…

【1】Python零基础起步

什么是编程(Programming) 编程是编定程序的中文简称&#xff0c;就是让计算机代码解决某个问题&#xff08;目的&#xff09;&#xff0c;对某个计算体系规定一定的运算方式&#xff0c;使计算体系按照该计算方式运行&#xff0c;并最终得到相应结果的过程&#xff08;手段&am…

Java Day 10 io流

IO流 1、前置知识 字符集1.1 标准ASCII1.2 GBK编码1.3 UTF-321.4 UTF-81.5 编码和解码方法 2、IO流2.1 流的分类2.2 FileInputStream2.2.1 常用方法 2.3 FileOutputStram2.3.1 常用方法2.3.2 文件复制案例 2.4 释放资源的方式2.4.1 try-catch-finally2.4.2 try-with-resource 1…

ftp和fxp哪个传传输快,传输大文件该怎么选择?

在当今数字化时代&#xff0c;大文件传输已成为日常工作和商业活动中不可或缺的一部分。无论是跨国公司的数据交换&#xff0c;还是个人用户的大型媒体文件分享&#xff0c;选择一个高效的传输协议至关重要。FTP和FXP是两种常用的文件传输方式&#xff0c;但在传输大文件时&…

nginx gzip性能优化 —— 筑梦之路

对比使用和不使用gzip static处理 1. 不使用 gzip static 时的 gzip 处理 如果你不使用 gzip_static 而只是 "gzip on"&#xff0c;它每次都会被压缩并发送。 虽然它实际上可能缓存在内存中&#xff0c;但传统观点是 "每次都会执行压缩处理&#xff0c;因此 CP…

【SRE系列之docker容器】--dockerfile镜像优化

dockerfile镜像优化 1.1 镜像优化方法 系统镜像采用ubuntu或者alpine&#xff0c;会比centos少1G左右编写业务镜像时从官网拉取镜像&#xff0c;其余配置根据业务需求再配置编写dockerfile时把不用的安装包卸载或者删除尽量减少run命令的使用&#xff08;一个run命令&#xf…

【兆易创新GD32H759I-EVAL开发板】图像处理加速器(IPA)的应用

GD32H7系列的IPA&#xff08;Image Pixel Accelerator&#xff09;是一个高效的图像处理硬件加速器&#xff0c;专门设计用于加速图像处理操作&#xff0c;如像素格式转换、图像旋转、缩放等。它的优势在于能够利用硬件加速来实现这些操作&#xff0c;相比于软件实现&#xff0…

YOLOv9实例分割教程|(二)验证教程

专栏地址&#xff1a;目前售价售价59.9&#xff0c;改进点30个 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 一、验证 打开分割验证文件&#xff0c;填入数据集配置文件、训练好的权重文件&…

go语言基础笔记

1.基本类型 1.1. 基本类型 bool int: int8, int16, int32(rune), int64 uint: uint8(byte), uint16, uint32, uint64 float32, float64 string 复数&#xff1a;complex64, complex128 复数有实部和虚部&#xff0c;complex64的实部和虚部为32位&#xff0c;complex128的实部…

yocto是个什么东东

yocto不是个什么东东 在我们了解Yocto项目是什么之前&#xff0c;让我们先了解一下它不是什么。 Yocto项目不是用于现有硬件的软件开发工具包&#xff08;SDK&#xff09;&#xff0c;而是用于构建这样一个工具包。 Yocto项目不是可以部署到硬件上的系统二进制镜像&#xff…

客服销冠偷偷用的提效神器!无广很实用

近期发现我的同事每天上班必登录的一款软件——客服宝聊天助手&#xff0c;用过才发现&#xff1a;真客服办公的提效神器&#xff01;感兴趣的小伙伴请往下看~一、客服宝的简介&#xff1a;客服宝聊天助手&#xff0c;是一款跨平台快捷回复工具。自带多种功能&#xff0c;有效帮…

leetcode判断子序列

本题中&#xff0c;我们可以删除原始字符串的一些字符但是不能改变其他字符的位置&#xff0c;这种求子序列的题都可以用动态规划来解决。 首先我们要确定dp数组的定义&#xff0c;这里我们将dp数组定义为dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的…

蓝桥杯[OJ 1621]挑选子串-CPP-双指针

目录 一、题目描述&#xff1a; 二、整体思路&#xff1a; 三、代码&#xff1a; 一、题目描述&#xff1a; 二、整体思路&#xff1a; 要找子串&#xff0c;则必须找头找尾&#xff0c;找头可以遍历连续字串&#xff0c;找尾则是要从头的基础上往后遍历&#xff0c;可以设头…

OSCP靶场--BlackGate

OSCP靶场–BlackGate 考点(1.redis rce 2. CVE-2021-4034提权) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.163.176 --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-14 03:32 EDT Nmap scan report for 192.168.163.…

MongoDB实战面试指南:常见问题一网打尽

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! MongoDB是一款流行的非关系型数据库&#xff0c;以其高效、可扩展的特性受到开发者的青睐。了解MongoDB的架构、存储引擎和数据结…

python 基础知识点(蓝桥杯python科目个人复习计划63)

今日复习内容&#xff1a;做题 例题1&#xff1a;蓝桥骑士 问题描述&#xff1a; 小蓝是蓝桥王国的骑士&#xff0c;他喜欢不断突破自我。 这天蓝桥国王给他安排了N个对手&#xff0c;他们的战力值分别为a1,a2,...,an&#xff0c;且按顺序阻挡在小蓝的前方。对于这些对手小…

剪辑设计软件如何跨系统使用?PC也能用Mac Final Cut

我猜你工作中&#xff0c;常常遇到这样那样的麻烦&#xff1a; 临时接手一个项目&#xff0c;之前的同事用Final Cut&#xff0c;而你是Windows系统&#xff1b; 临时有紧急需求要调整&#xff0c;而本地电脑却没有工作软件/性能不给力&#xff1b; 那这样的情况&#xff0c…

SSL证书如何实现数据加密传输?

在当前互联网的洪流中&#xff0c;用户对网站隐私与安全性的重视程度日益提升。为了确保用户信息和交易数据的安全传输&#xff0c;SSL证书在网络世界中扮演了关键角色。本文将深入解析SSL证书的核心功能及其重要作用。 1、SSL证书采用加密技术保障数据传输安全 通过应用公钥加…

Mysql 无法启动,mysql-bin.日志丢失删除处理

在linux操作系统中&#xff0c;当mysql无法启动时候&#xff0c;先看日志 2024-03-15T05:20:16.352075Z 0 [Warning] [MY-000081] [Server] option max_allowed_packet: unsigned value 107374182400 adjusted to 1073741824. 2024-03-15T05:20:16.352156Z 0 [Warning] [MY-010…

(008)Unity StateMachineBehaviour的坑

文章目录 StateMachineBehaviour同名函数的调用问题StateMachineBehaviour 的 OnState*、OnStateMachine* 的区别 StateMachineBehaviour同名函数的调用问题 1.如果脚本中&#xff0c;两个同名的函数都存在&#xff0c;那么两个函数都会被调用&#xff1b;如果只有其中一个同名…