算法通关村第九关-白银挑战二分查找与高频搜索树

大家好我是苏麟,今天看看二分查找相关的题目 .

大纲

    • 二分查找拓展问题
      • 山脉数组的峰顶索引
      • 寻找旋转排序数组中的最小值
    • 中序与搜索树
      • 二叉搜索树中的搜索
      • 验证二叉搜索树

二分查找拓展问题

山脉数组的峰顶索引

描述 :

符合下列属性的数组 arr 称为 山脉数组 :

  • arr.length >= 3
  • 存在 i(0 < i < arr.length - 1)使得:
    arr[0] < arr[1] < … arr[i-1] < arr[i]
    arr[i] > arr[i+1] > … > arr[arr.length - 1]

给你由整数组成的山脉数组 arr ,返回满足 arr[0] < arr[1] < … arr[i - 1] < arr[i] > arr[i + 1] > … > arr[arr.length - 1] 的下标 i

题目 :

LeetCode 852. 山脉数组的峰顶索引

852.山脉数组的封顶索引

在这里插入图片描述
分析 :

这个题其实就是前面找最小值的相关过程而已,最简单的方式是对数组进行一次遍历。

解析 :

class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        int length = arr.length;
        int n = 0;
        for(int i = 0; i< length - 1;i++){
            if(arr[i] > arr[i + 1]){
                n = i;
                break;
            }
        }
        return n;
    }
}

分析 :

使用二分来优化一下

因为此题是必为高峰数组 , 所以数组长度为 时下标1为最大值 .

解析 :

class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        int length = arr.length;
        if(length == 3){
            return 1;
        }
        int left = 1;
        int right = length - 1;
        while(left < right){
            int mid = (left + right) >>> 1;
            if(arr[mid - 1] < arr[mid] && arr[mid] < arr[mid + 1]){
                left = mid;
            }
            if(arr[mid - 1] > arr[mid] && arr[mid] > arr[mid + 1]){
                right = mid;
            }
            if(arr[mid - 1] < arr[mid] && arr[mid] > arr[mid + 1]){
                return mid;
            }
        }
        return left;
    }
}

寻找旋转排序数组中的最小值

描述 :

已知一个长度为 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]

注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]]

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

题目 :

LeetCode 153. 寻找旋转排序数组中的最小值 :

153.寻找旋转排序数组中的最小值

在这里插入图片描述
分析 :

一个不包含重复元素的升序数组在经过旋转之后,可以得到下面可视化的折线图:
在这里插入图片描述
其中横轴表示数组元素的下标,纵轴表示数组元素的值。图中标出了最小值的位置,是我们需要查找的目标。

我们考虑数组中的最后一个元素 xxx

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

在二分查找的每一步中,左边界为 left,右边界为 right,区间的中点为 mid,最小值就在该区间内。我们将中轴元素 nums[mid] 与右边界元素 nums[right] 进行比较,可能会有以下的三种情况:

第一种情况是 nums[mid] > nums[right]。如下图所示,这说明 nums[mid] 是最小值右侧的元素,因此我们可以忽略二分查找区间的右半部分。

在这里插入图片描述
第二种情况是nums[mid] > nums[right]。如下图所示,这说明 nums[mid] 是最小值左侧的元素,因此我们可以忽略二分查找区间的左半部分。

在这里插入图片描述
由于数组不包含重复元素,并且只要当前的区间长度不为 1,mid 就不会与 right 重合;而如果当前的区间长度为 1,这说明我们已经可以结束二分查找了。因此不会存在nums[mid] = nums[right]的情况。

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

解析 :

class Solution {
    public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while(left < right){
            int mid = (left + right) >>> 1;
            if(nums[mid] > nums[right]){
                left = mid + 1;
            }else{
                right = mid;
            }
        }
        return nums[left];
    }
}

中序与搜索树

在前面我们发现很多题使用前序、后序或者层次遍历都可以解决,但几乎没有中序遍历的。这是因为中序与前后序相比有不一样的特征,例如中序可以和搜索树结合在一起,但是前后序则不行。

二叉搜索树是一个很简单的概念,但是想说清楚却不太容易。简单来说就是如果一棵二叉树是搜索树,则按照中序遍历其序列正好是一个递增序列。比较规范的定义是:

  • 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  • 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  • 它的左、右子树也分别为二又排序树。下面这两棵树一个中序序列是 {3.6.9,10,14,16,19},一个是{3,6,9,10},因此都是搜索树:
    在这里插入图片描述
    搜索树的题目虽然也是用递归,但是与前后序有很大区别,主要是因为搜索树是有序的,就可以根据条件决定某些递归就不必执行了,这也称为“剪枝”。

二叉搜索树中的搜索

描述 :

给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

题目 :

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

700.二叉搜索树中的搜索
在这里插入图片描述
分析 :

本题看起来很复杂,但是实现非常简单,递归:

  • 如果根节点为空 root == null 或者根节点的值等于搜索值 val == root.val,返回根节点
  • 如果 val < root.val,进入根节点的左子树查找 searchBST(root.left, val)
  • 如果 val > root.val,进入根节点的右子树查找 searchBST(root.right, val)

解析 :

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        return searchNode(root,val);
    }
    public TreeNode searchNode(TreeNode root,int val){
        if(root == null){
           return null;
        }
        if(root.val == val){
            return root;
        }else{
            if(val < root.val){
               root = searchBST(root.left,val);
            }else{
                root =searchBST(root.right,val);
            }
        }
        return root;
    }
}

分析 :

迭代方式也很简单 , 只要值不相等就循环 , 循环到最后还没有就返回null .

解析 :

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        while(root != null && root.val != val){
           root = root.val > val ? root.left : root.right;
        }
        return root;
    }
}

验证二叉搜索树

描述 :

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

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

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

题目 :

LeetCode 98. 验证二叉搜索树

验证二叉搜索树

在这里插入图片描述
分析 :

我们就以这个为例 :

在这里插入图片描述

以此代码为例讲解 :

class Solution {
    public boolean isValidBST(TreeNode root) {
        return is(root);
    }

    long pre = Long.MIN_VALUE;
    public boolean is(TreeNode root){
        if(root == null){
            return true;
        }
        if(root.val <= pre){
            return false;
        }
        pre = root.val;
        return is(root.right);
    }
}

第一步 :

定义变量 : long pre = Long.MIN_VALUE; 他的值为 -9223372036854775808 远远比 1 小 用来比较

第二步 :

用pre 和 root.val 比较 如果小于就返回false 否则就把root.val赋值给 pre , 最后传入节点root.right

第三步 :

以 root.right 为根节点继续比较

而下面这个代码是 递归左节点的 , 如果根节点的左节点不是二叉搜索树返回false

       if(!is(root.left)){
            return false;
        }

解析 :

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        return is(root);
    }

    long pre = Long.MIN_VALUE;
    public boolean is(TreeNode root){
        if(root == null){
            return true;
        }
        if(!is(root.left)){
            return false;
        }
        if(root.val <= pre){
            return false;
        }
        pre = root.val;
        return is(root.right);
    }
}

这期就到这里了 , 下期见!

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

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

相关文章

JumpServer2023漏洞复现合集

本文主要复现JumpServer2023年出现的大批量漏洞&#xff0c;既是分享也是为了记录自己的成长&#xff0c;近期会持续更新。 1. JumpServer MongoDB远程代码执行漏洞&#xff08;CVE-2023-43651&#xff09; 1.1 漏洞级别 高危 1.2 漏洞描述 经过身份验证的用户可以利用Mon…

检验Pdfsharp.dll 支持的语言及对应的字体

文章目录 检验所支持语言的字体使用字体绘制文本并显示 PdfSharp 语言和字体的支持有限&#xff0c;有时候再本地电脑上能正常显示文本&#xff0c;但在其它电脑上就显示乱码或一个正方体&#xff0c;或&#xff1f;&#xff1f;。不同操作系统可能自带的字体本身就不一样&…

LeetCode2-两数相加

大佬解法 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val x; }* }*/ class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode pre new ListNode(0);ListNo…

ERR_PNPM_INVALID_WORKSPACE_CONFIGURATION packages field missing or empty

vue执行 pnpm install命令时&#xff0c;报 ERR_PNPM_INVALID_WORKSPACE_CONFIGURATION  packages field missing or empty错&#xff0c;在网上查询了很久&#xff0c;也没有传出来结果&#xff0c;最后发现是pnpm的版本不对引起的。 我先执行的是npm install -g pnpm&…

口袋参谋:如何找竞争小,优势大的蓝海词?

​ 作为淘宝天猫的中小卖家&#xff0c;99.99%的人都知道流量对于店铺的重要性&#xff0c;如果没有流量的话&#xff0c;店铺是肯定没有销量的。 提高流量的方式有很多种&#xff0c;比如优化宝贝图片、标题、关键词等&#xff0c;由于在淘宝天猫上同一宝贝的竞争力太大了…

成果分享丨学生学徒“行业”+大数据模型分享

学生学徒 阶段成果分享 为进一步提升学生学徒制学员的技术水平&#xff0c;增强学员的企业项目应用能力&#xff0c;助力学员全面发展。自学徒制开展以来&#xff0c;泰迪指导学员完成多项企业应用项目&#xff0c;开展多次项目经验分享交流&#xff0c;让学员在实践中不断学…

蘑菇街获得mogujie商品详情 API 返回值说明

速卖通API接口是速卖通平台提供的一种数据交换接口&#xff0c;可以帮助卖家快速获取平台上的商品信息、订单信息、用户信息等数据&#xff0c;以便在自己的应用程序中进行展示、管理或分析。 速卖通API接口可以通过以下步骤进行使用&#xff1a; 注册速卖通账号并获取API密钥…

如何将本地Portainer管理界面结合cpolar内网穿透工具实现远程浏览器访问

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

内网穿透的应用-通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

软件开发选择个人好?还是公司好?一篇文章带你了解

随着科技的发展&#xff0c;软件开发已成为一个相对复杂的行业&#xff0c;需要专业的技能和经验来保证项目的成功。然而&#xff0c;一些企业或个人可能会选择个人开发者进行软件开发&#xff0c;虽然这种选择可能会带来一些弊端。本文将探讨选择个人开发者进行软件开发的弊端…

分区格式化后的数据恢复指南,从此不再丢失重要数据

在日常生活中&#xff0c;我们使用电脑时&#xff0c;可能会因为种种原因需要对硬盘进行分区格式化。分区格式化是一种对硬盘进行重新划分存储空间的过程&#xff0c;它将删除该分区的所有数据&#xff0c;使其恢复到初始状态。然而&#xff0c;在执行分区格式化操作之后&#…

服务器数据恢复—VMware虚拟化下误操作导致服务器崩溃的数据恢复案例

服务器故障&分析&#xff1a; VMware虚拟化&#xff0c;vmfs文件系统&#xff0c;共3块磁盘。工作人员误操作将VMware虚拟化重装系统&#xff0c;服务器崩溃。 正常情况下&#xff0c;重装系统会导致文件系统元文件被覆盖。要恢复数据须找到重装系统前的文件系统残留信息并…

【EI会议征稿】第三届网络安全、人工智能与数字经济国际学术会议(CSAIDE 2024)

第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#xff09; 2024 3rd International Conference on Cyber Security, Artificial Intelligence and Digital Economy 第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#…

深入了解域名与SSL证书的关系

在如今数字化的世界里&#xff0c;网络安全成为我们关注的重要议题之一。为了确保数据在网络上传输的安全性&#xff0c;我们通常会采取各种安全措施&#xff0c;其中最常用的就是SSL证书。然而&#xff0c;很多人并不了解SSL证书是如何与域名相互关联的。 首先&#xff0c;我…

CentOS to 浪潮信息 KeyarchOS 迁移体验与优化建议

浪潮信息KeyarchOS简介 KeyarchOS即云峦操作系统(简称KOS), 是浪潮信息研发的一款面向政企、金融等企业级用户的 Linux 服务器操作系统。它基于Linux内核、龙蜥等开源技术&#xff0c;支持x86、ARM 等主流架构处理器&#xff0c;其稳定性、安全性、兼容性和性能等核心能力均已…

elasticsearch+canal增量、全量同步

目录 一、搭建环境&#xff1a; 1.1 下载软件上传到linux目录/data/soft下 1.2 把所有软件解压到/data/es-cluster 二、单节点&#xff08;多节点同理&#xff09;集群部署elasticsearch 2.1 创建es用户 2.2 准备节点通讯证书 2.3 配置elasticsearch&#xff0c;编辑/d…

Flutter应用-使用sqflite升级数据库

文章目录 问题描述具体做法代码示例更多条件限制升级 数据库迁移和备份简介数据库迁移数据库备份 问题描述 使用fluttter开发的应用程序发布后&#xff0c;发现数据库有些设计不合理。如何来更新数据库呢&#xff1f; 使用sqflite来处理数据库&#xff0c;但是第一版软件发布后…

【Vue3 + webStorm】 求助,vite.config.js代理不生效

求助&#xff0c;vite.config.js代理不生效 上面为代理写法 上面为vue组件中,axios跳转写法 网页控制台一直跳转不到8080端口&#xff0c;请问是为什么&#xff1f;

iframe渲染后端接口文件和实现下载功能

一&#xff1a;什么是iframe&#xff1f; 1、介绍 iframe 是HTML 中的一种标签&#xff0c;全称为 Inline Frame&#xff0c;即内联框架。它可以在网页中嵌入其他页面或文档&#xff0c;将其他页面的内容以框架的形式展示在当前页面中。iframe的使用方式是通过在HTML文档中插入…

opencv(2): 视频采集和录制

视频采集 相关API VideoCapture()cap.read()&#xff1a; 返回两个值&#xff0c;第一个参数&#xff0c;如果读到frame&#xff0c;返回 True. 第二个参数为相应的图像帧。cap.release() VideoCapture cv2.VideoCapture(0) 0 表示自动检测&#xff0c;如果在笔记本上运行&…