算法总结-二分查找

news2025/2/4 8:43:04

文章目录

    • 1.搜索插入位置
        • 1.答案
        • 2.思路
    • 2.搜索二维矩阵
        • 1.答案
        • 2.思路
    • 3.寻找峰值
        • 1.答案
        • 2.思路
    • 4.搜索旋转排序数组
        • 1.答案
        • 2.思路
    • 5.在排序数组中查找元素的第一个和最后一个位置
        • 1.答案
        • 2.思路
    • 6.寻找旋转排序数组中的最小值
        • 1.答案
        • 2.思路

1.搜索插入位置

1.答案
package com.sunxiansheng.arithmetic.day18;

/**
 * Description: 35. 搜索插入位置
 *
 * @Author sun
 * @Create 2025/1/30 10:11
 * @Version 1.0
 */
public class t35 {

    public static int searchInsert(int[] nums, int target) {
        // 左闭右闭,加等号
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            // 求中点
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            if (nums[mid] < target) {
                left = mid + 1;
            }
            if (nums[mid] > target) {
                right = mid - 1;
            }
        }
        // 如果找不到,就返回应该插入的位置
        return left;
    }
}
2.思路

左闭右闭,加等号,求中点,找不到就返回left

2.搜索二维矩阵

1.答案
package com.sunxiansheng.arithmetic.day18;

/**
 * Description: 74. 搜索二维矩阵
 *
 * @Author sun
 * @Create 2025/1/30 10:16
 * @Version 1.0
 */
public class t74 {

    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length;
        int n = matrix[0].length;
        // 左闭右闭
        int left = 0, right = m * n - 1;
        // 加等号
        while (left <= right) {
            // 求中点
            int mid = left + (right - left) / 2;
            // 转换中点下标为二维数组的下标
            int i = mid / n;
            int j = mid % n;
            if (matrix[i][j] == target) {
                return true;
            }
            if (matrix[i][j] < target) {
                left = mid + 1;
            }
            else if (matrix[i][j] > target) {
                right = mid - 1;
            }
        }
        return false;
    }
}
2.思路

就是在求中点的时候有些不一样,需要将数字转换为二维数组的下标,公式就是x / n 和 x % n

3.寻找峰值

1.答案
package com.sunxiansheng.arithmetic.day18;

/**
 * Description: 162. 寻找峰值
 *
 * @Author sun
 * @Create 2025/1/30 10:35
 * @Version 1.0
 */
public class t162 {

    public int findPeakElement(int[] nums) {
        // 左闭右闭加等号
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            // 判断是否大于左右边元素
            boolean leftSmaller = mid == 0 || nums[mid] > nums[mid - 1];
            boolean rightSmaller = (mid == nums.length - 1) || nums[mid] > nums[mid + 1];
            // 如果都大于,则当前元素就是峰值
            if (leftSmaller && rightSmaller) {
                return mid;
            }
            // 如果比左边的元素大,则峰值在右边
            if (leftSmaller) {
                left = mid + 1;
            } else {
                // 其余情况峰值在左边
                right = mid - 1;
            }
        }
        return -1;
    }
}
2.思路

除了二分老套路之外,还要判断是否大于左右边元素,如果都大于就是峰值,如果只是大于左边但是小于右边,那么峰值就在右边

4.搜索旋转排序数组

1.答案
package com.sunxiansheng.arithmetic.day18;

/**
 * Description: 33. 搜索旋转排序数组
 *
 * @Author sun
 * @Create 2025/1/30 11:05
 * @Version 1.0
 */
public class t33 {

    public static int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        // 左闭,右闭,加等号
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            // 求中点
            int mid = left + (right - left) / 2;
            // 找到了就直接返回
            if (target == nums[mid]) {
                return mid;
            }
            // 找不到,如果左边是有序的
            if (nums[mid] >= nums[left]) {
                // 判断是否在左边
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            } else {
                // 目前是右边有序,则判断是否在右边
                if (target <= nums[right] && target > nums[mid]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}
2.思路

左闭右闭加等号,求中点,如果找不到,就判断左边是不是有序的,如果左边有序,就进一步判断元素是否在左边,如果在就right = mid - 1,否则就是left = mid + 1,右边也是同理

5.在排序数组中查找元素的第一个和最后一个位置

1.答案
package com.sunxiansheng.arithmetic.day18;

/**
 * Description: 34. 在排序数组中查找元素的第一个和最后一个位置
 *
 * @Author sun
 * @Create 2025/1/30 11:23
 * @Version 1.0
 */
public class t34 {

    public int[] searchRange(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return new int[]{-1, -1};
        }
        return new int[]{getFirst(nums, target), getLast(nums, target)};
    }

    private int getFirst(int[] nums, int target) {
        // 左闭右闭,加等号
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            // 求中点
            int mid = left + (right - left) / 2;
            if (target <= nums[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        // 防止越界
        if (left < 0 || left > nums.length - 1) {
            return -1;
        }

        return nums[left] == target ? left : -1;
    }

    private int getLast(int[] nums, int target) {
        // 左闭右闭,加等号
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            // 求中点
            int mid = left + (right - left) / 2;
            if (target >= nums[mid]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        // 防止越界
        if (right < 0 || right > nums.length - 1) {
            return -1;
        }

        return nums[right] == target ? right : -1;
    }
}
2.思路

以找到第一个元素为例,首先还是二分老套路,然后如果target小于等于mid的元素,就在左边,否则在右边,注意退出循环后要防止越界,并且最后返回的时候也要判断left下的元素是不是那个元素!

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

1.答案
package com.sunxiansheng.arithmetic.day18;

/**
 * Description: 153. 寻找旋转排序数组中的最小值
 *
 * @Author sun
 * @Create 2025/1/30 13:07
 * @Version 1.0
 */
public class t153 {

    public int findMin(int[] nums) {
        // 左闭右闭加等号
        int left = 0, right = nums.length - 1;
        int res = nums[left];
        while (left <= right) {
            // 求中点
            int mid = left + (right - left) / 2;
            // 更新最小值
            res = Math.min(res, nums[mid]);

            // 将right指向的元素当做target
            if (nums[mid] <= nums[right]) {
                right = mid - 1;
            } else  {
                left = mid + 1;
            }
        }
        return res;
    }
}
2.思路

在二分的基础上,加了一个更新最小值的操作,并且将right指向的元素当做target进行更新左右边界的操作

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

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

相关文章

5.5.1 面向对象的基本概念

文章目录 基本概念面向对象的5个原则 基本概念 面向对象的方法&#xff0c;特点时其分析与设计无明显界限。虽然在软件开发过程中&#xff0c;用户的需求会经常变化&#xff0c;但客观世界对象间的关系是相对稳定的。对象是基本的运行实体&#xff0c;由数据、操作、对象名组成…

Java_类加载器

小程一言类加载器的基础双亲委派模型核心思想优势 各类加载器的职责 类加载器的工作流程举例&#xff1a;如何在Java中使用类加载器启动类加载器、扩展类加载器与系统类加载器输出解释自定义类加载器 类加载器与类冲突总结 小程一言 本专栏是对Java知识点的总结。在学习Java的过…

开源音乐管理软件Melody

本文软件由网友 heqiusheng 推荐。不过好像已经是一年前了 &#x1f602; 简介 什么是 Melody &#xff1f; Melody 是你的音乐精灵&#xff0c;旨在帮助你更好地管理音乐。目前的主要能力是帮助你将喜欢的歌曲或者音频上传到音乐平台的云盘。 主要功能包括&#xff1a; 歌曲…

一、TensorFlow的建模流程

1. 数据准备与预处理&#xff1a; 加载数据&#xff1a;使用内置数据集或自定义数据。 预处理&#xff1a;归一化、调整维度、数据增强。 划分数据集&#xff1a;训练集、验证集、测试集。 转换为Dataset对象&#xff1a;利用tf.data优化数据流水线。 import tensorflow a…

分析哲学:从 语言解剖到 思想澄清的哲学探险

分析哲学&#xff1a;从 语言解剖 到 思想澄清 的哲学探险 第一节&#xff1a;分析哲学的基本概念与公式解释 【通俗讲解&#xff0c;打比方来讲解&#xff01;】 分析哲学&#xff0c;就像一位 “语言侦探”&#xff0c;专注于 “解剖语言”&#xff0c;揭示我们日常使用的语…

鸿蒙物流项目之基础结构

目录&#xff1a; 1、项目结构2、三种包的区别和使用场景3、静态资源的导入4、颜色样式设置5、修改项目名称和图标6、静态包基础目录7、组件的抽离8、在功能模块包里面引用静态资源包的组件 1、项目结构 2、三种包的区别和使用场景 3、静态资源的导入 放在har包中&#xff0c;那…

[漏洞篇]SQL注入漏洞详解

[漏洞篇]SQL注入漏洞详解 介绍 把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行恶意的SQL命令。通过构造恶意的输入&#xff0c;使数据库执行恶意命令&#xff0c;造成数据泄露或者修改内容等&#xff0c;以达到攻击的目的。…

【最后203篇系列】006 -使用ollama运行deepseek-r1前后端搭建

说明 这块已经不算新内容了&#xff0c;年前搭完了后端&#xff08;ollama)&#xff0c;本来想早点分享的&#xff0c;但是当时的openwebui有点不给力&#xff0c;有些地方不适配&#xff0c;然后配置项找不到。所以前端没搭好&#xff0c;也就不完整&#xff1a;只能通过命令…

JDK-1.8.0_432安装(CentOS7)

目录 1、卸载系统自带JDK 2、下载安装包并解压 3、赋予可执行权限 4、设置环境变量 5、刷新环境变量 6、查看JDK版本 1、卸载系统自带JDK # 查询出自带的jdk rpm -qa | grep jdk rpm -qa | grep java # 将上述命令列出的包依次删除 rpm -e --nodeps xxxxxxx 2、下载…

【Linux】24.进程信号(1)

文章目录 1. 信号入门1.1 进程与信号的相关知识1.2 技术应用角度的信号1.3 注意1.4 信号概念1.5 信号处理常见方式概览 2. 产生信号2.1 通过终端按键产生信号2.2 调用系统函数向进程发信号2.3 由软件条件产生信号2.4 硬件异常产生信号2.5 信号保存 3. 阻塞信号3.1 信号其他相关…

股票入门知识

股票入门&#xff08;更适合中国宝宝体制&#xff09; 股市基础知识 本文介绍了股票的基础知识&#xff0c;股票的分类&#xff0c;各板块发行上市条件&#xff0c;股票代码&#xff0c;交易时间&#xff0c;交易规则&#xff0c;炒股术语&#xff0c;影响股价的因素&#xf…

用Python实现K均值聚类算法

在数据挖掘和机器学习领域&#xff0c;聚类是一种常见的无监督学习方法&#xff0c;用于将数据点划分为不同的组或簇。K均值聚类算法是其中一种简单而有效的聚类算法。今天&#xff0c;我将通过一个具体的Python代码示例&#xff0c;向大家展示如何实现K均值聚类算法&#xff0…

Flask代码审计实战

文章目录 Flask代码审计SQL注入命令/代码执行反序列化文件操作XXESSRFXSS其他 审计实战后记reference Flask代码审计 SQL注入 1、正确的使用直白一点就是&#xff1a;使用”逗号”&#xff0c;而不是”百分号” stmt "SELECT * FROM table WHERE id?" connectio…

Unity 2D实战小游戏开发跳跳鸟 - 跳跳鸟碰撞障碍物逻辑

在有了之前创建的可移动障碍物之后,就可以开始进行跳跳鸟碰撞到障碍物后死亡的逻辑,死亡后会产生一个对应的效果。 跳跳鸟碰撞逻辑 创建Obstacle Tag 首先跳跳鸟在碰撞到障碍物时,我们需要判定碰撞到的是障碍物,可以给障碍物的Prefab预制体添加一个Tag为Obstacle,添加步…

【玩转 Postman 接口测试与开发2_015】第12章:模拟服务器(Mock servers)在 Postman 中的创建与用法(含完整实测效果图)

《API Testing and Development with Postman》最新第二版封面 文章目录 第十二章 模拟服务器&#xff08;Mock servers&#xff09;在 Postman 中的创建与用法1 模拟服务器的概念2 模拟服务器的创建2.1 开启侧边栏2.2 模拟服务器的两种创建方式2.3 私有模拟器的 API 秘钥的用法…

mysql操作语句与事务

数据库设计范式 数据库设计的三大范式 ‌第一范式&#xff08;1NF&#xff09;‌&#xff1a;要求数据库表的每一列都是不可分割的原子数据项&#xff0c;即列中的每个值都应该是单一的、不可分割的实体。例如&#xff0c;如果一个表中的“地址”列包含了省、市、区等多个信息…

基于SpringBoot电脑组装系统平台系统功能实现五

一、前言介绍&#xff1a; 1.1 项目摘要 随着科技的进步&#xff0c;计算机硬件技术日新月异&#xff0c;包括处理器&#xff08;CPU&#xff09;、主板、内存、显卡等关键部件的性能不断提升&#xff0c;为电脑组装提供了更多的选择和可能性。不同的硬件组合可以构建出不同类…

【智力测试——二分、前缀和、乘法逆元、组合计数】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int mod 1e9 7; const int N 1e5 10; int r[N], c[N], f[2 * N]; int nr[N], nc[N], nn, nm; int cntr[N], cntc[N]; int n, m, t;void init(int n) {f[0] f[1] 1;for (int i …

玉米苗和杂草识别分割数据集labelme格式1997张3类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;1997 标注数量(json文件个数)&#xff1a;1997 标注类别数&#xff1a;3 标注类别名称:["corn","weed","Bean…

string例题

一、字符串最后一个单词长度 题目解析&#xff1a;由题输入一段字符串或一句话找最后一个单词的长度&#xff0c;也就是找最后一个空格后的单词长度。1.既然有空格那用我们常规的cin就不行了&#xff0c;我们这里使用getline,2.读取空格既然是最后一个空格后的单词&#xff0c;…