二分法题集1

news2024/11/21 1:23:34
1 二分查找

分析:

这是一道很简单的二分法题,定义两个指针和中间值middle,判断middle对应数组值与目标值的大小关系,从而对left和right进行修改。由于太过基础,代码简单基础就不多赘述。

目录

1 二分查找

分析:

代码展示:

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

分析:

代码展示:

3 搜索插入位置

分析:

代码展示:

4 x 的平方根 

分析:

代码展示:


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

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

分析:

这道题要求时间复杂度为logn,如果遍历数组时间复杂度最坏就是n,而时间复杂度为logn那就需要用二分法。

注意 二分法不一定要求数组有序,只要该数组存在二段性就可以用二分法。何为二段性,就是通过一个性质可以把数组划分为两段。比如在这道题中我们如果找第一个目标值就可以划分为小于target的为左端,大于等于targert的为右端。

我们定义两个指针left 和 right 分别指向下标0和下标nums.length - 1 。拿案例一分析,left到第一个最后一个7是小于8的区域,第一个8到right是大于等于8的区域。我们用middle来判断当前值与目标值的大小情况。如果小于目标值那么就让left = middle + 1;如果大于那么就让right = middle。

这时我们会发现如果目标值存在于数组,那么left最后一定会指向第一个目标值,因为小于目标值那么就会让left = middle +1,所以必然有middle + 1等于目标值,而且一定是第一个目标值。

代码展示:
class Solution {
    public int[] searchRange(int[] nums, int target) {
        if(nums.length == 0) {
            return new int[]{-1,-1};
        }
      
        int left = 0;
        int right = nums.length  - 1;
        int[] arr = new int[2];

        //找第一个数
        while(left < right) {
            int middle = left + (right - left) / 2;
            if(nums[middle] < target) {
                left = middle + 1;
            }else {
                right = middle;
            }
        }
        if(nums[left] == target)
        arr[0] = left;
        else arr[0] = -1;
        //找最后一个数
        left = 0;
        right = nums.length - 1;
        while(left < right) {
            int middle = left + (right - left + 1) / 2;
            if(nums[middle] <= target) {
                left = middle;
            }else{
                right = middle - 1;
            }
        }
        if(nums[left] == target) arr[1] = right;
        else arr[1] = -1;
        return arr;

    }
}

这里有很多细节:

1 while循环的条件必须是left < right:
第一点是因为,如果两个指针相遇那么一定会出结果只需要判断最后是不是目标值即可。第二点是因为(核心),如果条件是left <= right,那么代码就会死循环,当两个指针同时指向目标值时,由于nums[middle] = target,因此right = middle。此时就会不断循环。

2 我们可以看到寻找第一个数和最后一个数的middle求法是不一样的。middle = left + (right - left) / 2 这个求出的中间数是偏左的(比如left指向0下标,right指向1下标,那么这个公式求出的middle最后会指向0下标,相反middle = left + (right - left + 1)/2指向的就是指向1下标),由于上述我们提到如果数组中存在目标值,那么left最终一定会指向第一个目标值,所以我们要求middle是要偏向left一方,还有一个原因就是避免死循环,如果middle偏向right一方,那么right = middle;而求出的middle又指向right。

求最后一个数和求第一个数原理相同,只需要将letf到小于等于目标值划分为左区域,大于目标值划分为有区域,一旦nums[middle[大于目标值就让right = middle - 1.那么如果数组中存在该目标值,right一定会指向目标值的最后一位。

3 搜索插入位置

分析:

做完了上一道题,这道题就显得很简单了。我们看示例二,如果目标值是2,那么我们输出的结果是3的下标。我们可以想到,将小于目标值到left划分为一个区域,大于目标值到right划分为一个区域,那么当nums[middle]小于目标值时,left = middle + 1就能找到最后的结果。我们可以总结为第一个大于目标值的数等同于找第一个目标值,最后一个小于目标值的数等同于找最后一个目标值,方法都是一样的。

代码展示:
class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0 ;
        int right = nums.length - 1;
        if(nums[0] > target) return 0;
        if(nums[right] < target) return right + 1;
        while(left < right) {
            int middle = left + (right - left) / 2;
            if (nums[middle] < target) {
                left = middle + 1;
            }else{
                right = middle;
            }
        }
        return left;

    }
}

前两行代码是出去特殊情况,后面方法则等同于上一道题。

4 x 的平方根 

分析:

这道题我们仍然可以用二分法,比如定义一个x长的数组,并求出每一个数组下标的平方值,如果平方值是最后一个小于或者等于目标值的那么就返回该下标。二位破门上面总结了,如果是求最后一个小于目标值的,那么right = middle - 1一定会指向最后一个小于或者等于该目标值的下标。

代码展示:
class Solution {
    public int mySqrt(int x) {
       if(x < 1) return 0;
        long left = 1;
        long right = x / 2;
        while(left < right) {
            long middle = left + (right - left + 1) / 2;
            if(middle * middle > x) right = middle - 1;
            else left = middle ;
        }
        return (int)left;

    }
}

这里我们要考虑,范围,由于middle * middle结果太大所以需要用到Long类型,并且最后返回值要强转。

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

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

相关文章

Oracle 数据库维的建立

Oracle 数据库维的建立 SQL> select table_name from dict where table_name like %DBA%DIM%;TABLE_NAME ------------------------------ DBA_DIMENSIONS DBA_DIM_LEVELS DBA_DIM_LEVEL_KEY DBA_DIM_ATTRIBUTES DBA_DIM_HIERARCHIES DBA_DIM_CHILD_OF DBA_DIM_JOIN_KEYsel…

专题【链表】【考试题】刷题日记

题目列表 考试题&#xff08;22题&#xff09; 2024.04.04 146. LRU 缓存 707. 设计链表 138. 随机链表的复制 160. 相交链表 622. 设计循环队列 109. 有序链表转换二叉搜索树 460. LFU 缓存 355. 设计推特 725. 分隔链表 2487. 从链表中移除节点 日常复习题 876. 链表的中…

【智能算法应用】猎人猎物优化算法(HPO)在WSN覆盖中的应用

目录 1.算法原理2.数学模型3.结果展示4.参考文献 1.算法原理 【智能算法】猎人猎物算法&#xff08;HPO&#xff09;原理及实现 2.数学模型 3.结果展示 HPO设置区域边长为20&#xff0c;节点数为35&#xff0c;感知半径为2.5&#xff0c;实验结果如下&#xff1a; 4.参考…

iMazing 3 for Windows iOS设备管理软件2024最新功能解析

iMazing 3 for Windows是一款兼容Win和Mac的iOS设备管理软件。iMazing 3 for Windows能够将音乐、文件、消息和应用等数据从任何 iPhone、iPad 或 iPod 传输到 Mac 或 PC 上。 iMazing 3 win 版下载&#xff1a; https://souurl.cn/Qp6gFU iMazing 3 mac 版下载&#x…

一点点金融

一点点金融 价值投资 需求 > 有限 > 不可逆 > 优势 > 长期持有者多趋势分析 改进MACD策略&#xff0c;使用涨跌幅比值RSI计算MACD原始MACD计算改进思路&#xff1a;使用涨跌幅比值RSI计算MACD 价值投资 需求 > 有限 > 不可逆 > 优势 > 长期持有者多…

非关系型数据库——Redis基本操作

目录 一、Redis数据库常用命令 1.Set——存放数据 2.Get——获取数据 3.Keys——获取符合条件的键值 4.Exists——判断键值是否存在 5.Del——删除指定键值 6.Type——获取键值对应的类型 7.Rename——对已有键值重命名&#xff08;覆盖&#xff09; 8.Renamenx——对…

安全性基础知识

根据希赛相关视频课程汇总整理而成&#xff0c;个人笔记&#xff0c;仅供参考。本章核心为网络攻击和信息安全的实现技术 安全性基本概念 计算机安全原则&#xff1a; 在系统设计时&#xff0c;实现安全措施应具有简洁性&#xff1b; 系统的保护机制应该公开&#xff1b; 用户…

【Linux】使用cloudreve搭建个人网盘并传输文件

Cloudreve 是一个开源的个人网盘系统&#xff0c;能够帮助用户搭建属于自己的私有云存储服务。它支持多种存储后端&#xff0c;包括本地存储、远程FTP/SFTP存储、以及云存储服务如阿里云OSS、腾讯云COS和Amazon S3等。Cloudreve具有友好的用户界面和丰富的功能&#xff0c;比如…

Git相关的内容来这里看看吧

Git相关的内容来这里看看吧 1、Centos 安装Git方法一&#xff1a;yum命令安装(可能不是最新版本)方法二&#xff1a;源码安装Git配置以及如何配置密钥 Git常用命令参考链接 1、Centos 安装Git 方法一&#xff1a;yum命令安装(可能不是最新版本) yum install -y git卸载已安装…

虚拟机打不开

问题 另一个程序已锁定文件的一部分&#xff0c;进程无法访问 打不开磁盘“G:\centeros\hadoop104kl\hadoop100-cl2.vmdk”或它所依赖的某个快照磁盘。 模块“Disk”启动失败。 未能启动虚拟机。 原因 前一次非正常关闭虚拟机导致.lck 文件是VMWare软件的一种磁盘锁文件&…

计算机网络练习-计算机网络概述与性能指标

计算机网络概述 ----------------------------------------------------------------------------------------------------------------------------- 1. 计算机网络最据本的功能的是( )。 1,差错控制 Ⅱ.路由选择 Ⅲ,分布式处理 IV.传输控制 …

Tcl学习笔记(二)——表达式、字符串

目录 1. 表达式 算数操作符 关系操作符 逻辑操作符 按位操作符 选择操作符 数学函数 字符串操作 2. 字符串 字符串长度、大小写转换、裁剪、重复 字符串类型 字符的获取 字符串的添加、删除、替换 字符串的比较 字符串的简单搜索 字符串的匹配 格式化…

C语言中strlen函数的实现

C语言中strlen函数的实现 为了便于和strlen函数区别&#xff0c;以下命令为_strlen。 描述&#xff1a;实现strlen&#xff0c;获取字符串的长度&#xff0c;函数原型如下&#xff1a; size_t strlen(const char *str);_strlen实现&#xff1a; size_t _strlen(const char*…

开源流程图表库(04):mxGraph,都是可视化编辑,导出使用。

mxGraph是一个用于创建和展示图形的JavaScript库。它提供了丰富的功能和工具&#xff0c;可以用于构建各种类型的图形应用程序&#xff0c;包括流程图、组织结构图、网络拓扑图等。 mxGraph的编辑器 一、mxGraph的特点和功能 以下是一些mxGraph的特点和功能&#xff1a; 强大…

微信小程序的页面交互2

一、自定义属性 &#xff08;1&#xff09;定义&#xff1a; 微信小程序中的自定义属性实际上是由data-前缀加上一个自定义属性名组成。 &#xff08;2&#xff09;如何获取自定义属性的值&#xff1f; 用到target或currentTarget对象的dataset属性可以获取数据 &#xff…

dm8 备份与恢复

dm8 备份与恢复 基础环境 操作系统&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) 数据库版本&#xff1a;DM Database Server 64 V8 架构&#xff1a;单实例1 设置bak_path路径 --创建备份文件存放目录 su - dmdba mkdir -p /dm8/backup--修改dm.ini 文件…

小米汽车su7全色系展示源码

源码简介 小米汽车全色系展示源码&#xff0c;小米汽车su7全色系展示源码 安装教程 纯HTML&#xff0c;直接将压缩包上传网站目录解压即可 首页截图 源码下载 小米汽车su7全色系展示源码-小8源码屋源码简介 小米汽车全色系展示源码&#xff0c;小米汽车su7全色系展示源码 …

从永远到永远-Git中tag的使用

Git中tag的使用 1.tag的作用2.使用背景3.tag的使用1.种类2.创建标签3.查看标签3.推送标签4. 删除标签: 4.idea可视化操作1.创建标签2.推送标签 999 删除、指定commit、验证暂时不表 1.tag的作用 Tag(标签)用来记录某个特定的提交(commit)。一个 Tag 被用来标记重要的历史节点&…

MOS管用作开关管时,工作在哪个区?

MOS管作为开关管使用时&#xff0c;主要工作在两个区域&#xff1a;截止区和饱和区&#xff0c;有时也会通过线性区。 截止区&#xff1a; 当MOS管的栅极-源极电压&#xff08;Vgs&#xff09;低于阈值电压&#xff08;Vth&#xff09;时&#xff0c;MOS管处于截止状态。在这种…

企业如何设计和实施有效的网络安全演练?

现实世界中&#xff0c;武装部队一直利用兵棋推演进行实战化训练&#xff0c;为潜在的军事冲突做准备。随着当今的数字化转型&#xff0c;同样的概念正在以网络安全演习的形式在组织中得到应用&#xff0c;很多企业每年都会基于合理的网络攻击场景和事件响应做一些测试和模拟。…