代码随想录刷题-数组-二分查找

news2024/9/24 5:24:45

文章目录

  • 写在前面
  • 原理
  • 习题
    • 题目1
      • 思路和代码
    • 题目-2

写在前面

这个专栏是记录我刷代码随想录过程中的随想和总结。每一小节都是根据自己的理解撰写的,文章比较短,主要是为了记录和督促自己。刷完一章后,我会再单独整理一篇文章来总结和分享。

本节对应代码随想录中:代码随想录-二分查找

原理

二分法(Binary Search)是一种在有序数组中查找特定元素的算法。它的原理是,将数组分成两半,然后判断目标元素在哪一半中,然后再继续将这一半分成两半,直到找到目标元素或者确定目标元素不存在为止。

前提条件:二分法适用于有序数组或有序列表中的查找操作,且元素必须支持比较操作。

一旦有重复元素的时候,二分法返回的下标可能不唯一

算法步骤如下:

1.将数组按照中间元素分成两部分。

2.如果中间元素等于目标元素,直接返回中间元素的下标。

3.如果中间元素大于目标元素,说明目标元素在左半部分,将右边界移动到中间元素的左边。

4.如果中间元素小于目标元素,说明目标元素在右半部分,将左边界移动到中间元素的右边。

5.重复以上步骤,直到找到目标元素或者确定目标元素不存在。

习题

题目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]之间。

思路和代码

这道题目说了元素是有序的,而且无重复元素,那么在查找的时候就可以使用二分法进行查找

写二分法会遇到三种情况

  • 初始 right = nums.size()-1 还是 nums.size()
  • right = middle-1 还是 right = middle
  • while(left <= right) 还是 while(left < right)

如下面这张图,left 等不等于 right,right 的取值也会不一样,可分为两种写法
在这里插入图片描述

  • 如果初始写 right=nums.size()-1 即7个元素中 L=0,R=6,那么查找区间就是[0,6],M 为3。
  • 此时应该写 right = middle-1 。如上图 M=3时没有匹配成功,那么下次的区间应该是[0,2],因为 M=3已经判断一次了
  • 如上图如果 M=1时仍不是我们要找的元素,假如此时还是大于待查找元素,那么 R=0。此时 left=right=0是有意义的,也就是我们需要最后判定下 L=0时的1是不是待查找元素,因此 while 的条件为 while(left <= right)

这三种情况其实就是要互相对应,第二种类型在代码随想录中有解释

代码如下

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};

注意取中间值时没有使用 middle = (left + right) / 2 而是 middle = left + ((right - left) / 2)

这样写能够避免 left + right 可能数值太大导致溢出的问题

例子:在闭区间[3,9]中 right-left=6,说明3到9需要走6步,再除2得3,说明从3到9走3步可以走到中间的位置

题目-2

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 n = nums.size();
        int left = 0, right = n - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > target) {
                right = right - 1;
            } else {
                left = left + 1;
            }
        }
        return left;
    }
};

观察上述代码可以发现这题和上题只是在上题 return -1 处改成了 return left

解释: 上题的 return -1 和这里的 return left 都代表着所查找元素没有出现给定数组中的情况

至于目标值被插入的顺序为什么是 left。根据 if 的判断条件,left 左边的值一直保持小于 target,right 右边的值一直保持大于等于 target,而且 left 最终一定等于 right+1

  • 左边:[2,4]查找1,left=0,right=1,一轮后 left=0,right=-1
  • 中间:[2,4]查找3,left=0,right=1,一轮后 left=1,right=1,二轮后 left=1,right=0
  • 右边:[2,4]查找5,left=0,right=1,一轮后 left=1,right=1,二轮后 left=2,right=1

当 left=right=middle 时,若仍未找到,此时要么 right-- 要么 left++,最终一定是 left=right+1

这么一来,循环结束后,left 左边的部分全部小于 target,所以最终答案一定在 left 的位置

参考:搜索插入位置- 力扣(LeetCode)

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

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

相关文章

【JVM 由浅入深】JVM入门

JVM入门1. 概述 今天我们对JVM 进行入门讲解&#xff0c;让我们了解下什么是JVM&#xff0c;是专门为Java服务的一款产品吗&#xff1f;&#xff1f;&#xff1f; 好了废话不多说了&#xff0c;让我们开始吧 2. 详解 2.1 Java 是跨平台的 为什么是Java是跨平台的呢&#xff0c…

LeetCode 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指没有子节点…

oneblog_justauth_三方登录配置【Github】

文章目录oneblog添加第三方平台github中创建三方应用完善信息登录oneblog添加第三方平台 1.oneblog管理端&#xff0c;点击左侧菜单 网站管理——>社会化登录配置管理 ,添加一个社会化登录 2.编辑信息如下&#xff0c;选择github平台后复制redirectUri,然后去github获取cl…

Arduino添加ESP32开发板

【2023年3月4日】 最近要在新电脑上安装Arduino&#xff0c;需要进行一些配置&#xff0c;正好记录一下&#xff01; Arduino2.0.1 下的开发板添加操作。 ESP32开发板GitHub链接&#xff1a; GitHub - espressif/arduino-esp32: Arduino core for the ESP32Arduino core for…

ICASSP2023|达摩院语音实验室入选论文全况速览

近日&#xff0c;语音技术领域国际会议ICASSP公布了本届论文审稿结果&#xff0c;阿里巴巴达摩院语音实验室有14篇论文被大会收录。本次被接收的论文研究方向涵盖语音识别、语音唤醒、语音增强、说话人日志、语义理解、多模态预训练等。 01 TOLD: A Novel Two-Stage Overlap-…

实验楼项目

创建虚拟环境命令&#xff1a;python -m venv venv 项目整体分为六个个模块&#xff1a;用户信息相关模块、机构相关模块、课程相关模块、用户操作相关模块&#xff0c;评论区模块 搜索模块。 # 项目功能概括&#xff1a; 1、首先具有完整的用户登录&#xff0c;邮箱注册以及…

JDBC的实现(IDEA版)

前期准备 开发环境&#xff1a; IDEA 2021.1.3 JAVA 1.8 MYSQL 8.0.32 msql用户名:root 密码&#xff1a;123 下载MySQL JDBC 驱动 前往MySQL官网下载对应版本的MySQL Connector/J驱动 &#xff08;下载地址&#xff1a;https://dev.mysql.com/downloads/connector/j/&#xff…

基于rootfs构建Docker镜像

1. 背景 在实际工作中&#xff0c;由于系统本身版本过低&#xff0c;在接受新项目时出现系统版本过低而无法开始工作的问题。 为了解决该问题&#xff0c;使用Docker构建基于ubuntu-18.04的Docker镜像&#xff0c;以解决版本兼容问题。 2. 构建rootfs 2.1. 下载ubuntu-18.0…

HCIA复习1

HCIA复习 抽象语言---->编码 编码---->二进制 二进制--->电信号 处理电信号 OSI参考模型----OSI/RM 应用层 表示层 会话层 传输层 端口号&#xff1a;0-65535&#xff1b;1-1023是注明端口 网络层 IP地址 数据链路层 物理层 ARP协议 正向ARP---通过IP地址获取目的MAC地…

云服务器Ubuntu(无桌面)安装远程桌面

如果主机上安装的ubuntu是桌面版&#xff0c;打开桌面共享即可使用Windows的远程桌面进行链接。详细参考ubuntu20.10中设置桌面共享的三种方式(任选其一) 的第一部分。 本文主要说明如何在Ubuntu云服务器上安装远程桌面。 一、安装桌面环境 在 Ubuntu 源仓库有很多桌面环境供…

路由协议(OSPF、ISIS、BGP)实验配置

目录 OSPF基础实验 建立OSPF邻居 配置虚连接 配置接口的网络类型 配置特殊区域 配置路由选路 配置路由过滤 ISIS基础实验配置 配置ISIS邻居建立 配置认证 配置路由扩散 配置路由过滤 配置定时器 BGP基础实验配置 建立BGP对等体 建立IBGP对等体 建立EBGP对等体…

自动驾驶规划控制软硬一体化控制器解决方案(一)

随着社会的进步&#xff0c;汽车工业和电子科技发展迅速&#xff0c;车载电子器件的数量越来越多&#xff0c;汽车 电子的平台集成度越来越高&#xff0c;两者的融合正在革新着人们的驾乘体验。本文基于 x86 SoC 进 行系统设计&#xff0c;实现高效的汽车智能驾驶舱技术和高级驾…

ASGARD:单细胞导向的药物发现

异质性&#xff0c;或更具体地说&#xff0c;病变组织中的不同的细胞群&#xff0c;是许多复杂疾病治疗失败的主要原因&#xff08;如癌症、阿尔茨海默症、中风和COVID-19等&#xff09;&#xff0c;也是精准医疗成功的主要障碍。近年来&#xff0c;单细胞技术&#xff0c;特别…

【项目精选】基于Java的模拟写字板的设计与实现(视频+论文+源码)

点击下载源码 此系统是使用Java语言实现简易写字板程序&#xff0c;能够进行输入文字操作&#xff0c;并具有新建文件&#xff0c;打开文件&#xff0c;保存文件&#xff0c;退出&#xff0c;复制&#xff0c;粘贴&#xff0c;剪切&#xff0c;全选&#xff0c;撤销等多种基本…

电子技术——晶体管尺寸

电子技术——晶体管尺寸 在本节我们介绍关于IC设计的一个重要的参数晶体管尺寸&#xff08;例如长度和长宽比&#xff09;。我们首先考虑MOS反相器。 反相器尺寸 为了说明 (W/L)(W/L)(W/L) 的尺寸大小以及 (W/L)p(W/L)_p(W/L)p​ 和 (W/L)n(W/L)_n(W/L)n​ 的比例问题对于MO…

CENTO OS上的网络安全工具(十八)ClickHouse及编程环境部署

这篇其实去年就写好了&#xff0c;孰知就在12月31日那一天打进决赛圈&#xff0c;一躺&#xff0c;二过年&#xff0c;三休假&#xff0c;四加班&#xff0c;居然到了三个月以后&#xff0c;才有机会将它发出来…… 一年也就四个季度不是&#xff0c;实在是光阴荏苒&#xff0c…

代码随想录|day6|哈希表篇-- 242.有效的字母异位词 、349. 两个数组的交集 、202. 快乐数、1. 两数之和

总链接https://docs.qq.com/doc/DUEtFSGdreWRuR2p4?u329948d2f0044f34b7cbe72503f0b572 242.有效的字母异位词 链接&#xff1a;代码随想录 class Solution { public:bool isAnagram(string s, string t) {//两种做法&#xff0c;一种是int f[26]的数组,一种是map /*第一种&a…

历史大讲堂:这是真·图形化 苹果系统历史回顾(上)

众所周知&#xff0c;米国有个非常牛掰的公司叫苹果&#xff0c;想必大家对这个logo不陌生吧。 目前已发布的苹果产品有iPhone、iPad、iPod等等&#xff0c;简直花样繁多&#xff0c;而且各种功能很好用&#xff0c;我的手机就是一部苹果iPhone X。 等一下&#xff0c;似乎扯远…

14个Python处理Excel的常用操作,非常好用

自从学了Python后就逼迫用Python来处理Excel&#xff0c;所有操作用Python实现。目的是巩固Python&#xff0c;与增强数据处理能力。 这也是我写这篇文章的初衷。废话不说了&#xff0c;直接进入正题。 数据是网上找到的销售数据&#xff0c;长这样&#xff1a; 一、关联公式:…

第十四届蓝桥杯第三期模拟赛 【python】

第十四届蓝桥杯第三期模拟赛 【python】 文章目录第十四届蓝桥杯第三期模拟赛 【python】✨最小的十六进制&#xff08;python的16进制&#xff09;❓️问题描述答案提交&#x1f9e0;思路&#x1f5a5;︎参考答案✨Excel的列&#xff08;进制转化&#xff09;❓️问题描述答案…