【代码随想录 | Leetcode | 第一天】数组 | 二分查找 | 边界问题 | 34-35-69-367-704

news2024/11/24 19:52:06

前言

欢迎来到小K的Leetcode|代码随想录|专题化专栏,今天将为大家带来二分查找边界问题(循环不变量规则)的分享

目录

  • 前言
  • 704. 二分查找
  • 367. 有效的完全平方数
  • 69. x 的平方根
  • 35. 搜索插入位置
  • 34. 在排序数组中查找元素的第一个和最后一个位置
  • 总结


核心

在开始今天的内容之前,我们首先要明确什么情况下可以使用二分——有序、无重复元素,当然也可以通过变形得到,再者就是边界条件的限定,while(left < right) 还是 while(left <= right),到底是right = middle呢,还是要right = middle - 1呢?不要着急,我们通过下面的题目来揭开它的面目~

704. 二分查找

✨题目链接点这里
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

提示:

你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。

第一种写法,我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right]

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[mid] > target) right 要赋值为 mid - 1,因为当前这个nums[mid]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int mid=left+((right-left)>>2);
            if(nums[mid]==target) return mid;
            else if(nums[mid]>target) right=mid-1;
            else left=mid+1;
        }
        return -1;
    }
};

在这里插入图片描述

第二种写法,定义 target 是在一个在左闭右开的区间里,也就是[left, right)

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[mid] > target) right 更新为 mid,因为当前nums[mid]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为mid,即:下一个查询区间不会去比较nums[mid]
class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size();
        while(left<right)
        {
            int mid=left+((right-left)>>2);
            if(nums[mid]==target) return mid;
            else if(nums[mid]>target) right=mid;
            else left=mid+1;
        }
        return -1;
    }
};

在这里插入图片描述


367. 有效的完全平方数

✨题目链接点这里
给你一个正整数 num 。如果 num 是一个完全平方数,则返回 true ,否则返回 false 。完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。不能使用任何内置的库函数,如 sqrt 。
示例 1:

输入:num = 16
输出:true
解释:返回 true ,因为 4 * 4 = 16 且 4 是一个整数。

示例 2:

输入:num = 14
输出:false
解释:返回 false ,因为 3.742 * 3.742 = 14 但 3.742 不是一个整数。

提示:

1 <= num <= 231 - 1

这个题目就是简单的二分应用

class Solution {
public:
    bool isPerfectSquare(int num)
    {
        int left=0,right=num;
        while(left<=right){
            int mid=left+((right-left)>>1);
            long square=(long)mid*mid;
            if(square==num) return true;
            else if(square<num) left=mid+1;
            else right=mid-1;
        }
        return false;
    }
};

在这里插入图片描述


69. x 的平方根

✨题目链接点这里
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

提示:

0 <= x <= 231 - 1

此题我还琢磨了好半天,最后发现思路很简单,由于这里是取整,所以所求的平方<=x,满足这种情况的我们记录一下(可能是答案),继续判断,看看有没有更贴切的,没有就返回记录的那种情况,剩下的情况用常规二分判断即可

class Solution {
public:
    int mySqrt(int x) 
    {
        int left=0,right=x,ans=-1;
        while(left<=right){
            int mid=left+((right-left)>>1);
            if((long long)mid*mid<=x){
                ans=mid;
                left=mid+1;
            }
            else right=mid-1;
        }
        return ans;
    }
};

在这里插入图片描述


35. 搜索插入位置

✨题目链接点这里
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 为 无重复元素 的 升序 排列数组
-104 <= target <= 104

在这里插入图片描述
就下面的四总情况:

  • 目标值在数组所有元素之前
  • 目标值等于数组中某一个元素
  • 目标值插入数组中的位置
  • 目标值在数组所有元素之后
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int mid=left+((right-left)>>1);
            if(nums[mid]==target) return mid;
            else if(nums[mid]>target) right=mid-1;
            else left=mid+1;
        }
        return right+1;
    }
};

在这里插入图片描述


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

✨题目链接点这里
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

提示:

0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109

这题的关键就在于找上下边界,其实很简单,以第一个为例(左边界)就是在二分等于的基础上加判断条件当前中间元素等于目标值且不等于前面的一个元素或者当前中间元素等于目标值且为第一个元素,其他判断和二分一样

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        int left=getLeftIdx(nums,target), right=getRightIdx(nums,target);
        return {left,right};
    }
private:
    int getLeftIdx(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int mid=left+((right-left)>>1);
            if(nums[mid]==target)
                if( mid==0 || nums[mid]!=nums[mid-1])
                    return mid;
                else right=mid-1;
            else if(nums[mid]>target) right=mid-1;
            else left=mid+1;
        }
        return -1;
    }
    int getRightIdx(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int mid=left+((right-left)>>1);
            if(nums[mid]==target)
                if( mid==nums.size()-1 || nums[mid]!=nums[mid+1])
                    return mid;
                else left=mid+1;
            else if(nums[mid]>target) right=mid-1;
            else left=mid+1;
        }
        return -1;
    }
};

在这里插入图片描述


总结

小K今天学习了二分查找的边界问题,以及几种场景下二分的切换,打卡第一天~加油!

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

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

相关文章

PN结、形成过程、单向导电性、伏安特性、电容效应

目录 1.1.3PN结 PN结形成过程&#xff1a; PN结的单向导电性&#xff1a; PN结的伏安特性 PN结的电容效应 1.1.3PN结 形成&#xff1a;由于扩散运动而形成 扩散运动&#xff1a;物质总是从浓度高的地方向浓度低的地方运动&#xff0c;这种由于浓度差而产生的运动称为扩散运…

微服务 云原生:微服务相关技术简要概述

后端架构演进 单体架构 所谓单体架构&#xff0c;就是只有一台服务器&#xff0c;所有的系统、程序、服务、应用都安装在这一台服务器上。比如一个 bbs 系统&#xff0c;它用到的数据库&#xff0c;它需要存储的图片和文件等&#xff0c;统统都部署在同一台服务器上。 单体架…

ubuntu20.04配置vscode

下载&#xff1a; https://az764295.vo.msecnd.net/stable/660393deaaa6d1996740ff4880f1bad43768c814/code_1.80.0-1688479026_amd64.debhttps://az764295.vo.msecnd.net/stable/660393deaaa6d1996740ff4880f1bad43768c814/code_1.80.0-1688479026_amd64.deb 安装&#xff1a…

MySQL基础篇第9章(子查询)

文章目录 1、需求分析与问题解决1.1 实际问题1.2 子查询的基本使用1.3 子查询的分类 2、单行子查询2.1 单行比较操作符2.2 代码示例2.3 HAVING中的子查询2.4 CASE中的子查询2.5 子查询中的空值问题2.6 非法使用子查询 3、多行子查询3.1 多行比较操作符3.2 代码示例3.3 空值问题…

vuepress - - - 首页底部版权信息加a标签超链接跳转或备案信息跳转链接

修改前 默认的底部版权信息只能填写纯文本&#xff0c;加不了超链接跳转等。 对应\docs\README.md内容&#xff1a; 修改后 修改后&#xff0c;点击Zichen跳转会打开新的网页。 看官网例子 底部添加了备案号跳转链接。 找到官网的github部署的文件。点导航栏中的“指…

flutter开发实战-实现webview与Javascript通信JSBridge

flutter开发实战-实现webview与H5中Javascript通信JSBridge 在开发中&#xff0c;使用到webview&#xff0c;flutter实现webview是使用原生的插件实现&#xff0c;常用的有webview_flutter与flutter_inappwebview 这里使用的是webview_flutter&#xff0c;在iOS上&#xff0c;…

【IMX6ULL驱动开发学习】20. input子系统(按键实现ls命令)

一、input子系统相关结构体 二、input子系统实例实现&#xff1a; static struct input_dev *key_input;...... ....../* 1.申请空间 */ key_input input_allocate_device(); if(key_input NULL){printk("input alloc failed\n");return -ENOMEM; } /* 2.设置事件类…

Go实现WebSocket

Go语言标准包里面没有提供对WebSocket的支持&#xff0c;但是在由官方维护的go.net子包中有对这个的支持&#xff0c;你可以通过如下的命令获取该包&#xff1a; go get golang.org/x/net/websocket WebSocket分为客户端和服务端&#xff0c;接下来我们将实现一个简单的例子:…

云进销存是什么意思,云进销存系统该如何选?

云进销存是指基于云计算技术的一种进销存管理系统&#xff0c;云进销存系统可以帮助企业或中小商户实时监控库存情况、优化采购和销售流程、提高物流效率&#xff0c;以及生成各类报表和统计分析&#xff0c;从而提升企业或商户的运营效率和管理水平。 一、云进销存对中小商户有…

C#,数值计算——不完全 Beta 函数(incomplete beta function)的源代码

Incomplete Beta Function The incomplete beta function (also called the Euler Integral) is a generalized β-function; An independent integral (with integral bounds from 0 to x) replaces the definite integral. The formula is: Where: 0 ≤ x ≤ 1, a, b > 0…

Pro白嫖esri数据

最近用Pro比较多,想跟大家谈谈一些关于Pro的 技巧。在谈之前,我想问大家一个问题,你真的了解ArcGIS Pro吗? 我想大多数刚刚接触Pro的用户应该是把Pro当做像Map一样的数据处理分析工具,只是简单的从其他地方下载数据来加入工程进行处理和分析 或许在你眼里的Pro和Map仅有…

在Orangepi上使用raspberry的dashboard

树莓派实验室整了一个比较酷的dashboard&#xff0c;可以用来显示树莓派状态&#xff0c;主要内容是基于js和php来实现&#xff0c;因为orangepi的用户名和密码都是一个套路&#xff0c;首先想到能不能移植。 https://www.rstk.cn/news/860562.html?actiononClick 首先需要做…

Docker把公共镜像推送到harbor私服的流程(企业级)

如果构建项目时&#xff0c;使用了k8s docker Jenkins的模式。 那么我们在docker构建镜像时&#xff0c;如果需要使用了Nodejs&#xff0c;那么我们必须得从某个资源库中拉取需要的Nodejs。 在企业里&#xff0c;正常都会把自己项目涉及的库都放在harbor私服里。 下面讲一下&…

数据分类分级

数据分类是数据管理的第一步&#xff0c;是数据治理的先行条件。当前&#xff0c;数据应用方兴未艾。“数据”作为新的生产要素资源&#xff0c;支撑供给侧结构性改革、驱动制造业转型升级的作用日益显现&#xff0c;正成为推动质量变革、效率变革、动力变革的新引擎。但与此同…

python3+requests+unittest实战系列【二】

前言&#xff1a;上篇文章python3requestsunittest&#xff1a;接口自动化测试&#xff08;一&#xff09;已经介绍了基于unittest框架的实现接口自动化&#xff0c;但是也存在一些问题&#xff0c;比如最明显的测试数据和业务没有区分开&#xff0c;接口用例不便于管理等&…

ROS中bag的录制、播放和使用

文章目录 前言一、bag录制二、bag信息查看三、bag播放四、bag的使用&#xff08;以A-LOAM为例&#xff09; 前言 传感器获取到的信息&#xff0c;有时我们可能需要实时处理&#xff0c;有时可能只是采集数据&#xff0c;事后分析&#xff0c;比如: 机器人导航实现中&#xff0…

Tomcat 基础

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 二、安装 三、 目录结构 四、启停 五、配置文件 1. server.xml (1) Server (2) Listener (3) GlobalNamingResources (4) Service 01.Connector (1) port…

硬件故障恢复出文件之后数据库故障处理---惜分飞

客户那边硬件故障(raid损坏磁盘超过了极限,导致raid offline),通过硬件恢复出来数据文件,然后尝试自行恢复,我接手的时候大量数据文件resetlogs scn异常. 重建控制文件报错 WARNING: Default Temporary Tablespace not specified in CREATE DATABASE command Default Tempora…

Git安装详解(写吐了,看完不后悔)

Git 是一个非常流行的分布式版本控制系统&#xff0c;它帮助开发者管理和跟踪项目中的代码变化。通俗地说&#xff0c;可以认为 Git 就像是一个代码的时间机器&#xff0c;它记录了项目从开始到结束的每一次代码变动。 无论你是个人开发者还是团队成员&#xff0c;掌握 Git 都能…

三防平板在工业生产中的物料追溯与供应链管理

科技的不断发展和技术的不断进步&#xff0c;越来越多的企业开始关注物料追溯和供应链管理的重要性。特别是在工业生产中&#xff0c;确保物料的安全性和可追溯性对于提高生产效率和产品质量至关重要。10.1寸三防平板采用新一代英特尔Jasper Lake平台处理器赛扬RN5100&#xff…