二分法相关使用

news2024/11/17 11:50:56

文章目录

  • 1. 在一个有序数组中,找某个数是否存在
  • 2. 在一个有序数组中,找大于等于某个数最左侧的位置
  • 3. 在一个有序数组中, 找小于等于某个数最右侧的位置
  • 4. 局部最大值问题

1. 在一个有序数组中,找某个数是否存在

在线OJ:704. 二分查找

有序数组下的二分思路如下:

  • 由于这里是有序数组, 我们可以可以先得到中点位置, 中点可以把数组分为左右两边;
  • 如果中点位置的值等于目标值, 直接返回中点位置;
  • 如果中点位置的值小于目标值, 则去数组中点左侧按同样的方式查找;
  • 如果中点位置的值大于目标值, 则取数组中点右侧按同样的方式查找;
  • 如果最后没有找到, 则返回 -1.

代码实现如下:

class Solution {
    public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        int mid = 0;
        while (left < right) {
            mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
}

2. 在一个有序数组中,找大于等于某个数最左侧的位置

在线OJ: 35. 搜索插入位置

通过题目示例可以知道, 这个题本质上就是在一个有序数组中, 找大于等于某个数最左侧的位置, 如果不存在, 就返回数组长度 (表示插入在最末尾位置).

这个题只需要在 1 代码基础上进行简单改动即可, 在 1 中, 我们找到满足条件的位置就直接返回了; 而在本题中, 因为要找到最左侧的位置, 所以, 在遇到 nums[mid] >= target 的时候, 不用直接返回, 而是先把位置 mid 记录下来, 然后继续去左侧找是否还有满足条件的更左边的位置.

代码实现如下:

class Solution {
    public int searchInsert(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        int mid = 0;
        int ans = nums.length;
        while (left <= right) {
            mid = left + (right - left) / 2;
            if (nums[mid] >= target) {
                ans = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return ans;
    }
}

3. 在一个有序数组中, 找小于等于某个数最右侧的位置

和 2 的实现基本是一样的, 就不赘述了, 代码如下:

/**
 * 有序数组中找到 <=num 最右的位置
 */
public static int mostRightIndex(int[] arr, int num) {
    if (arr == null || arr.length == 0) {
        return -1;
    }
    int left = 0;
    int right = arr.length - 1;
    int mid = 0;
    int ans = -1;
    while (left <= right) {
        mid = left + (right - left) / 2;
        if (arr[mid] <= num) {
            ans = mid;
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return ans;
}

4. 局部最大值问题

在线OJ:162. 寻找峰值

思路如下:

题目中已经说明, 对于所有有效的 i 都有nums[i] != nums[i + 1], 所以, 不会出现相邻相等的情况.

假设数组长度为 N, 首先判断 0 号位置的数和 N-1 号位置的数是不是峰值位置; 0 号位置只需要和 1 号位置比较, 如果 0 号位置大; 0 号位置就是峰值位置 (0 号位置位置左边没有元素, 可以认为是无穷小), 可以直接返回.

N-1 号位置只需要和 N-2 号位置比较, 如果 N-1 号位置大, N-1 号位置就是峰值位置 (N-1 号位置右边没有元素, 可以认为是无穷大), 可以直接返回.

如果 0 号位置和 N-1 在上轮比较中均是最小值, 那么数组的样子必然是如下情况:

img

由上图可知, 0 到 1 这段是增长趋势, N-2 到 N-1 这段是下降趋势, 那么峰值位置必在[1…N-2]之间出现;

此时可以通过二分来找峰值位置, 先来到中点位置, 假设中点为 mid, 如果中点位置的值比左右两边的值都大, 即:

arr[mid] > arr[mid+1] && arr[mid] > arr[mid-1]

则 mid 位置就是峰值位置, 直接返回即可.

否则, 有如下两种情况:

  • 情况一, mid 位置的值比 mid - 1 位置的值小, 趋势如下图, 此时可以在[1...(mid-1)]区间内继续二分;

img

  • 情况二, mid 位置的值比 mid + 1 位置的值小, 趋势如下图, 此时可以在[(mid+1)...(N-2)]区间内继续二分;

img

如果最后都没找到, 返回 -1 即可.

代码实现如下:

class Solution {
    public int findPeakElement(int[] arr) {
        int len = arr.length;
        if (arr == null || len == 0) {
            return -1;
        }
        if (len == 1) {
            return 0;
        }
        if (arr[0] > arr[1]) {
            return 0;
        }
        if (arr[len - 1] > arr[len - 2]) {
            return len - 1;
        }

        int left = 1;
        int right = len - 2;
        int mid= 0;
        while (left <= right) {
            mid = left + (right-left) / 2;
            if (arr[mid] > arr[mid-1] && arr[mid] > arr[mid + 1]) {
                return mid;
            }
            if (arr[mid] < arr[mid - 1]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
}

补充一下如果想要实现找局部最小值的话, 思路是一样的, 把代码符号改改就行了, 代码如下:

/**
 * 局部最小值问题
 * arr数组中的元素直接一定是相邻不相等的元素
 * 可以是无序的
 */
// 返回任意一个局部最小值即可
public static int oneMinIndex(int[] arr) {
    int len = arr.length;
    if (arr == null || len == 0) {
        return -1;
    }
    if (len == 1) {
        return 0;
    }
    if (arr[0] < arr[1]) {
        return 0;
    }
    if (arr[len - 1] < arr[len - 2]) {
        return len - 1;
    }

    int left = 1;
    int right = len - 2;
    int mid= 0;
    while (left <= right) {
        mid = (left + right) / 2;
        if (arr[mid] > arr[mid - 1]) {
            right = mid - 1;
        } else if (arr[mid] > arr[mid + 1]) {
            left = mid + 1;
        } else {
            return mid;
        }
    }
    
    return -1;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亚马逊:分布式计算宣言

文章目录 分布式计算宣言背景关键概念基于服务的模型基于工作流的模型和数据域应用概念跟踪状态变化对进行中的工作流程元素进行更改工作流程和 DC 客户订单处理 分布式计算宣言 创建时间&#xff1a; 1998 年 5 月 24 日 修订日期&#xff1a; 1998 年 7 月 10 日 背景 很…

uni-app nvue页面中使用video视频播放组件

我遇到的问题是&#xff0c;在nvue页面引用video组件&#xff0c;然后啥也没显示的&#xff0c;显示了无法控制播放&#xff0c;折腾了好久&#xff0c;在这里记录下来&#xff01;希望可以帮助到需要的人 我的代码是这样的&#xff08;src换成官方的举例&#xff09; <vi…

查看mysql数据库版本的方式(cmd命令和navicat)

目录 一、使用场景 二、查看方式 &#xff08;一&#xff09;cmd命令方式 &#xff08;二&#xff09;navicat16软件里面查看 &#xff08;三&#xff09;navicat试用版本查看的方式 一、使用场景 在有些时候需要调试系统的时候&#xff0c;就要看数据库的版本&#xff…

【致敬未来的攻城狮计划】— 连续打卡第二十三天:RA2E1的存储器基础知识

系列文章目录 1.连续打卡第一天&#xff1a;提前对CPK_RA2E1是瑞萨RA系列开发板的初体验&#xff0c;了解一下 2.开发环境的选择和调试&#xff08;从零开始&#xff0c;加油&#xff09; 3.欲速则不达&#xff0c;今天是对RA2E1 基础知识的补充学习。 4.e2 studio 使用教程 5.…

【MySQL】数据库基础操作一:建库与建表

目录 &#x1f31f;前言 &#x1f308;1、常见的关系型数据库 &#x1f31f;数据库的基本操作 &#x1f308;1、常用数据库的操作 &#x1f308;2、常用的数据类型 &#x1f308;3、表的基本操作 &#x1f345;创建表的一个小练习 &#x1f31f;前言 &#x1f…

基于Python的特征工程:数据预处理(一)

一、概述 特征工程是机器学习工作流程中不可或缺的一环&#xff0c;它将原始数据转化为模型可理解的形式。数据和特征的质量决定了机器学习的上限&#xff0c;而模型和算法则是逼近这个上限的手段。因此&#xff0c;特征工程的重要性不言而喻。其主要工作涉及特征的采集、预处…

干货 | 带你用Process完成中介效应检验

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 今天我们给大家介绍下平常常用的也很简单的操作&#xff0c;如何使用spss中process插件进行中介效应检验。 Process的功能很强大&#xff0c;它的下载也是免费开源的&#xff0c;在spss的…

springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5

part1 part2 part3 part4 part5 本页 6 移动端短信发送和手机验证码登入 6.1 短信发送 6.2 手机验证码登入 6.1 短信发送 6.1.1整体分析 2. 3. 注册登入阿里云账户。找到短信服务&#xff0c;设置短信签名&#xff08;上面图片的阿里云、菜鸟裹裹、天猫…&#xff09;&…

体验 Dolly V2

体验 Dolly V2 1. 什么是 Dolly V22. Github 地址3. 安装 Miniconda34. 创建虚拟环境5. 部署 Dolly V26. 编写测试程序7. 运行测试程序 1. 什么是 Dolly V2 Databricks的dolly-v2-12b&#xff0c;是一个在 Databricks 机器学习平台上训练的指令跟随型大型语言模型&#xff0c;…

【2023/05/06】EDSAC

Hello&#xff01;大家好&#xff0c;我是霜淮子&#xff0c;2023倒计时第1天。 Share 去成为你本该成为的人&#xff0c;任何时候都不会太晚。 &#xff08;出处&#xff1a;乔治艾略特&#xff09; Day1 EDSAC&#xff1a;存储程序式计算机的开山之作。 part1 EDSAC&…

redis(3)

redis客户端登陆: redis-cli -h host -p port -a password String类型的应用场景: 1)String通常用于保存单个字符串或者JSON格式的字符串数据 2)因为String类型通常是二进制安全的&#xff0c;因此你完全可以把一个图片内容当作字符串来进行存储 3)计数器&#xff0c;是常规的k…

java错题总结(31-33页)

假定Base b new Derived&#xff08;&#xff09;; 调用执行_360笔试题_牛客网 ABDC 只要是被子类重写的方法&#xff0c;不被super调用都是调用子类方法 ------------------------------------------------------------------------------------------- --------…

【Linux】Linux安装Redis(图文解说详细版)

文章目录 前言第一步&#xff0c;下载安装包第二步&#xff0c;上传安装包到/opt下&#xff08;老规矩了&#xff0c;安装包在opt下&#xff09;第三步&#xff0c;解压安装包第四步&#xff0c;编译第五步&#xff0c;安装第六步&#xff0c;配置redis第七步&#xff0c;设置开…

Matplotlib 初使用

五一假期时候&#xff0c;我在自己的电脑上安装了 matplotlib 安装步骤请转至&#xff1a;matplotlib 安装介绍 现在&#xff0c;我终于可以在自己电脑上学习 matolotlib 数学绘图库了&#xff0c; 说终于两个字&#xff0c;是完全是在安装过程中确实历经了折磨&#xff0c;根…

基于AT89C51单片机的电子钟设计与仿真

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87759735?spm1001.2014.3001.5503 源码获取 主要内容&#xff1a; 设计一个电子钟,实现对时、分、秒的显示的控制,电路采用24小时计时方式。另一个功能是秒表功能…

mysql : name like “%name“; 索引一定失效吗?

场景如下&#xff1a; MySQL版本如下&#xff1a; 表结构如下&#xff1a;索引结构如下&#xff1a; 查询语句以及执行计划如下&#xff1a; 第一条查询语句&#xff1a; select name from em where name like ‘%b’; 可以发现使用了name 字段创建的索引 第二条查询语句&…

02-Java基础编程

Java基础编程 Java 基础语法Java 标识符变量变量的类型Java 基本数据类型基本数据类型转换 运算符常见运算符运算符的优先级 程序流程控制分支语句循环结构常用的循环结构循环的嵌套break 和 continue 关键字 数组一维数组多维数组的使用Arrays 工具类的使用数组中常见的异常 J…

AcWing——方格迷宫(有点不一样的迷宫问题)

4943. 方格迷宫 - AcWing题库 1、题目 给定一个 n 行 m 列的方格矩阵。 行从上到下依次编号为 1∼n&#xff0c;列从左到右依次编号为 1∼m。 第 i 行第 j 列的方格表示为 (i,j)。 矩阵中的方格要么是空地&#xff08;用 . 表示&#xff09;&#xff0c;要么是陷阱&#xf…

前后端身份认证:session身份认证,JWT认证

文章目录 前后端身份认证1、概述2、不同开发模式下的身份认证3、关于HTTP协议的无状态性4、Cookie4.1 介绍4.2 cookie特点4.3 cookie分类4.4 Cookie在session身份认证中的作用4.5 Cookie不具有安全性 5、Session认证5.1 Session认证过程5.2 Session认证原理图5.3 Session认证的…

【Linux】多线程 --- 线程概念 控制 封装

从前种种&#xff0c;譬如昨日死。从后种种&#xff0c;往如今日生。 文章目录 一、线程概念1.重新理解用户级页表1.1 进程资源如何进行分配呢&#xff1f;&#xff08;地址空间页表&#xff09;1.2 虚拟地址如何转换到物理地址&#xff1f;&#xff08;页目录页表项&#xff0…