算法通关村第九关 | 二叉树查找和搜索树原理

news/2024/7/2 23:50:08

1. 二分查找的扩展问题

1.1山脉数组的巅峰索引

LeetCode852:题目核心意思是在数组中,从0到i是递增的,从i+1到数组最后是递减的,让你找到这个最高点。

三种情况:

  • mid在上升阶段的时候,满足arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1];

  • mid在顶峰的时候,满足arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1];

  • mid在下降阶段,满足arr[mid] < arr[mid - 1] && arr[mid] > arr[mid + 1];

根据三种情况我们可以写出二分查找的代码:

//山脉数组最高山峰问题
    public static int peakindex(int[] arr) {
        //长度为3的时候最高点索引是1
        if (arr.length == 3) {
            return 1;
        }
        int left = 0;
        int right = arr.length - 2;//减2,否则下面会越界
        //需要注意是否是等号问题,当=的时候是峰顶,不需要再进行处理,
        while (left < right) {
            int mid = left + ((right - left) >> 1);
            if (arr[mid] < arr[mid - 1] && arr[mid] > arr[mid + 1]) {
                return mid;
            } else if (arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1]) {
                left = mid + 1;
            } else if (arr[mid] < arr[mid - 1] && arr[mid] > arr[mid + 1]) {
                right = mid - 1;
            }
        }
        return left;
    }

1.2 旋转数字的最小数字

LeetCode153,已知一个长度为n的数组,预先按照升序排列,经由1-n次旋转后,得到输入数组。例如原数组nums = [0,1,2,4,5,6,7]在变化后可能得到:

  • 若旋转4次,则可以得到[4,5,6,7,0,1,2];

  • 若旋转7次,则可以得到[0,1,2,4,5,6,7];

我们可以考虑数组的最后一个元素x,在最小值右侧的元素(不包括最后一个元素本身),它们的值一定都严格小于x,而在最小值左侧的元素,它们的值一定都严格大于x,因此,我们可以根据这一条性质,通过二分查找方法找出最小值。

  1. 第一种情况nums[pivot] < nums[high] ,这说明nums[pivot]是最小值右侧的元素,因此我们可以忽略右半部分,

  2. 第二种情况nums[pivot] > nums[high],这说明nums是最小值左侧元素,因此我们可以忽略二分查找的左半部分

  3. 由于数组中不包含重复元素,并且只要当前区间长度不为1,pivot就不会和high重合;而如果当前的区间长度为1.这说明我们已经可以结束二分查找了。因此不会存在nums[pivot] = nums[high]的情况。

  4. 当二分查找结束时,我们就找到最小值所在的位置。

 图1,第一种情况

  图2,第二种情况

//旋转数字的最小数字
    public int findMin(int[] arr) {
        int low = 0;
        int high = arr.length - 1;
        //low=high的时候停止
        while (low < high){
            int pivot = low + ((high - low) >> 1);
            if (arr[pivot] < arr[high]){
                high = pivot;
            }else {
                low = pivot + 1;
            }
        }
        return arr[low];
    }

2.中序与搜索树原理

二叉搜索树概念:

  • 若它的左子树不为空,则左子树上的所有节点的值均小于它根节点的值;

  • 若它的右子树不为空,则右子树上所有节点的值均大于它的根节点的值;

  • 它的左右子树也分别为二叉树。下面给出两个例子

 注意事项:

是左子树或右子树所有节点大于或小于根节点,不是左结点或右节点,注意是所有。

2.1 二叉搜索树中搜索特定的值

LeetCode700:给定的二叉搜索树的根节点和一个值,你需要在BST中找到节点值等于给定值的节点,返回该节点的子树,若节点不存在,则返回null;

类似于二分查找的方式,递归:

2.2 验证二叉搜索树

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

根据前面的定义来递归判断:

    //这句话在方法外面只创建一次
    int pre = Integer.MIN_VALUE;
    public boolean isBST(TreeNode root){
        if (root == null){
            return true;
        }
        if (!isBST(root.left)){
            return false;
        }
        //访问当前节点,如果当前节点小于等于中序遍历的前一个结点,说明不满足BST
        if (root.val <= pre){
            return false;
        }
        pre = root.val;
        //右子第一个左或中节点与根节点比较
        return isBST(root.right);
    }

  • 如果根节点root == null或者根节点的搜索值val == root.val,返回根节点

  • 如果val < root.val,进入根节点的左子树查找searchBST(root.left);

  • 如果val > root.val,进入根节点的右子树查找searchBST(root.right)

  •     public TreeNode searchBST(TreeNode root,int val){
            if (root == null || val == root.val) return root;
            return val < root.val?searchBST(root.left,val):searchBST(root.right,val);
        }
  • 如果根节点root == null或者根节点的搜索值val == root.val,返回根节点

  • 如果val < root.val,进入根节点的左子树查找searchBST(root.left);

  • 如果val > root.val,进入根节点的右子树查找searchBST(root.right)


http://lihuaxi.xjx100.cn/news/1451683.html

相关文章

生态系统NPP及碳源、碳汇模拟教程

详情点击链接&#xff1a;生态系统NPP及碳源、碳汇模拟教程 第一&#xff1a;CASA模型 1.1 碳循环模型 1.2 CASA模型原理 1.3 CASA下载与安装 1.4 CASA注意事项 第二&#xff1a;CASA初步操作 2.1 ENVI界面 2.2 ENVI 数据及格式 2.3 基于ENVI的CASA模拟 2.4 CASA结果分…

渗透测试成功的8个关键

渗透测试 (penetration test)并没有一个标准的定义&#xff0c;国外一些安全组织达成共识的通用说法是&#xff1a;渗透测试是通过模拟恶意黑客的攻击方法&#xff0c;来评估计算机网络系统安全的一种评估方法。这个过程包括对系统的任何弱点、技术缺陷或漏洞的主动分析&#x…

python自动化办公的一些小工具,函数组件

上一篇文章写了怎么自动化写一个月报&#xff0c;其中有很多很好用的函数组件&#xff0c;都被我封装为了函数&#xff0c;功能很好用。下面一一介绍&#xff1a; 1.添加汇总函数 输入一个pandas的数据框&#xff0c;就会返回一个加了汇总行的数据框。 def add_summary_row(d…

Flink的常用算子以及实例

1.map 特性&#xff1a;接收一个数据&#xff0c;经过处理之后&#xff0c;就返回一个数据 1.1. 源码分析 我们来看看map的源码 map需要接收一个MapFunction<T,R>的对象&#xff0c;其中泛型T表示传入的数据类型&#xff0c;R表示经过处理之后输出的数据类型我们继续往…

用AI攻克“智能文字识别创新赛题”,这场大学生竞赛掀起了什么风潮?

文章目录 一、前言1.1 大赛介绍1.2 项目背景 二、基于智能文字场景个人财务管理创新应用2.1 作品方向2.2 票据识别模型2.2.1 文本卷积神经网络TextCNN2.2.2 Bert 预训练微调2.2.3 模型对比2.2.4 效果展示 2.3 票据文字识别接口 三、未来展望 一、前言 1.1 大赛介绍 中国大学生…

leetcode-413. 等差数列划分(java)

等差数列划分 leetcode-413. 等差数列划分题目描述双指针 上期经典算法 leetcode-413. 等差数列划分 难度 - 中等 原题链接 - 等差数列划分 题目描述 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。 例如&#xff0…

TiDB数据库的安装配置

一、 TiDB 软件和硬件环境建议配置 Linux 操作系统版本要求 Linux 操作系统 版本 Red Hat Enterprise Linux 7.3 及以上的 7.x 版本 CentOS 7.3 及以上的 7.x 版本 Oracle Enterprise Linux 7.3 及以上的 7.x 版本 Amazon Linux 2 Ubuntu LTS 16.04 及以上的版本 …

UE4/UE5 照明构建失败 “Lightmass crashed”解决“数组索引越界”

在构建全局光照时,经常会出现“Lightmass crashed”的错误,导致光照构建失败。本文将分析这一问题的原因,并给出解决建议。 UE4 版本4.26 报错如下: <None> === Lightmass crashed: === Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:d:\build…