035.搜索插入位置

题意

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

难度

简单

示例

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

分析 1

同样,在不考虑时间复杂度的情况下,我们来看一下这道题的解法。

①、如果目标值在数组中,那就是直接遍历数组,找到和 target 相等的元素,返回索引即可。

②、如果目标值不在数组中,题目要求返回插入的位置,那么由于数组是排序过的(默认都是正序),那么第一个大于 target 的元素位置,就是 target 应该插入的位置。

class Solution {public int searchInsert(int[] nums, int target) {for (int i = 0; i < nums.length; i++) {if (nums[i] >= target) {return i;}}//如果target最大,直接放在最后,也就是返回数组长度return nums.length;}
}

直接一个 for 循环 + 一个 if 判断,就搞定了,并且仍然能击败 100% 的 Java 用户。

分析 2

不过,题目仍然要求我们使用时间复杂度为 O(log n) 的算法,那就需要使用二分查找了。

试试 Arrays.binarySearch() 方法吧,如果找到了,直接返回索引,如果没找到,返回 -index - 1,这个值就是 target 应该插入的位置。

class Solution {public int searchInsert(int[] nums, int target) {int index = Arrays.binarySearch(nums, target);return index >= 0 ? index : -index - 1;}
}

为什么 -index - 1 就是 target 应该插入的位置呢?

来看一下 Arrays.binarySearch() 的源码:

public static int binarySearch(int[] a, int key) {return binarySearch0(a, 0, a.length, key);
}private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) {int low = fromIndex;int high = toIndex - 1;while (low <= high) {int mid = (low + high) >>> 1;int midVal = a[mid];if (midVal < key)low = mid + 1;else if (midVal > key)high = mid - 1;elsereturn mid; // key found}return -(low + 1);  // key not found.
}

如果找到了,直接返回索引,这没啥好说的。如果没找到,也就是当 while 循环结束时,说明数组中没有目标值。

return -(low + 1):返回一个负数,表示目标值不在数组中。这种返回值的含义如下:

  • low 是在数组中第一个大于目标值的位置。
  • -(low + 1) 会返回一个负数,这样可以通过检查返回值是否为负数来判断目标值是否存在于数组中。
  • 之所以返回 -(low + 1) 而不是 -low,是因为如果 low 的值是 0,直接返回 -low 会得到 0,这与找到的索引 0 混淆。通过返回 -(low + 1),总是返回一个负数,这样可以明确区分查找成功和查找失败。

那既然应该返回 0 的时候返回了-1,那么通过 -(-(low + 1)) - 1 也就是 low,就是 target 应该插入的位置。

来看一下题解效率,很不错。

分析 3

当然了,我们也可以手写二分查找法,不用 Arrays.binarySearch()。和之前 “在排序数组中查找元素的第一个和最后一个位置”的写法差不多。

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

我们来模拟一下当输入 nums = [1, 3, 5, 6] 和 target = 7 时,代码的执行过程。

第一次循环的时候,left = 0,right = 3,计算 mid:

mid = left + (right - left) / 2= 0 + (3 - 0) / 2= 1

比较 nums[mid] 和 target:

nums[mid] = nums[1] = 3

由于 nums[1] < target,更新 left:

left = mid + 1 = 1 + 1 = 2

第二次循环的时候,left = 2,right = 3,计算 mid:

mid = left + (right - left) / 2= 2 + (3 - 2) / 2= 2

比较 nums[mid] 和 target:

nums[mid] = nums[2] = 5

由于 nums[2] < target,更新 left:

left = mid + 1 = 2 + 1 = 3

第三次循环的时候,left = 3,right = 3,计算 mid:

mid = left + (right - left) / 2= 3 + (3 - 3) / 2= 3

比较 nums[mid] 和 target:

nums[mid] = nums[3] = 6

由于 nums[3] < target,更新 left:

left = mid + 1 = 3 + 1 = 4

此时 left = 4,right = 3,left > right,跳出循环,返回 left,即返回 4。

题解效率仍然不错。

总结

这道题仍然考察的是二分查找法,由此可见二分查找法的重要性。

去 B站搜了一下,这个 up 讲的不错,推荐大家看一下。

数据结构合集 - 折半查找(二分查找)

力扣地址:. - 力扣(LeetCode)

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

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

相关文章

Open vSwitch 中的 vswitchd 事件上报

一、数据包转发流程与 vswitchd 事件上报 Open vSwitch 的数据包转发流程如下图所示&#xff1a; 在数据包的转发流程中&#xff0c;提到过慢速路径的概念&#xff1a;即当数据包在内核空间无法完全处理时&#xff0c;会产生 upcall 调用&#xff0c;将数据包从内核空间转发到用…

大众点评_token,mtgsig

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本文章未经许可禁止转载&#xff0…

⌈ 传知代码 ⌋【算法】实体关系抽取

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

亲测解决远程服务器内存满了、用vs code的ssh连接不上

最近小虎跑实验产生了一个多Tb的数据&#xff0c;直接把服务器的内存占满了。导致程序停了、ssh也连接不上了。 环境 Ubuntu 22.04VSCodessh 解决方法 用cmder或其他ssh的命令窗口直接连接&#xff08;不要用vscode等软件&#xff09;&#xff0c;然后清/移动一下多余的文件…

【漏洞复现】六零导航页 _include_file.php 任意文件上传漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

鸿蒙 游戏来了 鸿蒙版 五子棋来了 我不允许你不会

团队介绍 作者:徐庆 团队:坚果派 公众号:“大前端之旅” 润开鸿生态技术专家,华为HDE,CSDN博客专家,CSDN超级个体,CSDN特邀嘉宾,InfoQ签约作者,OpenHarmony布道师,电子发烧友专家博客,51CTO博客专家,擅长HarmonyOS/OpenHarmony应用开发、熟悉服务卡片开发。欢迎合…

.NET MAUI Sqlite数据库操作(一)

一、安装 NuGet 包 安装 sqlite-net-pcl 安装 SQLitePCLRawEx.bundle_green 二、配置数据库&#xff08;数据库文件名和路径&#xff09; namespace TodoSQLite; public static class Constants {public const string DatabaseFilename "TodoSQLite.db3";//数据库…

this指针如何使C++成员指针可调用

在C中&#xff0c;this指针是一个隐藏的指针&#xff0c;指向当前对象实例。它在成员函数中自动可用&#xff0c;用于访问该对象的成员变量和成员函数。理解this指针的工作原理有助于理解为什么指向成员的指针是可调用的。在本文中&#xff0c;我们将详细探讨this指针的概念&am…

如何实现内网穿透?快解析-免费内网穿透工具

在现如今的ipv4时代&#xff0c;随着上网电脑及其他智能设备越来越多&#xff0c;公网IP地址出现了枯竭的情况。近几年&#xff0c;内网穿透这个词被不断提及&#xff0c;这也是在无公网IP环境下实现异地访问的一种可行办法&#xff0c;下面我就给大家介绍一下内网穿透的原理。…

结构型模式-桥接模式

桥接模式是什么 桥接模式是一种结构型设计模式&#xff0c;用于将抽象部分和其具体实现部分解耦&#xff0c;使它们可以独立变化。该模式通过将抽象和实现部分分离&#xff0c;使它们可以独立地扩展和变化。 在桥接模式中&#xff0c;有两个关键角色&#xff1a;抽象部分和实现…

LLMs:《A Decoder-Only Foundation Model For Time-Series Forecasting》的翻译与解读

LLMs&#xff1a;《A Decoder-Only Foundation Model For Time-Series Forecasting》的翻译与解读 导读&#xff1a;本文提出了一种名为TimesFM的时序基础模型&#xff0c;用于零样本学习模式下的时序预测任务。 背景痛点&#xff1a;近年来&#xff0c;深度学习模型在有充足训…

云计算在保险行业的应用:太平财险团财险理赔新核心业务系统案例

随着科技的快速发展&#xff0c;云计算技术已经成为推动保险行业数字化转型的重要力量。云计算为保险公司提供了弹性、可扩展的计算资源&#xff0c;使其能够灵活应对业务高峰和低谷&#xff0c;提高业务运营效率和风控水平。太平财险与太平金科联合开发的“团财险理赔新核心业…

PCA与LDA

共同点 降维方法&#xff1a; PCA和LDA都是数据降维的方式&#xff0c;它们都能通过某种变换将原始高维数据投影到低维空间。 数学原理&#xff1a; 两者在降维过程中都使用了矩阵特征分解的思想&#xff0c;通过对数据的协方差矩阵或类间、类内散度矩阵进行特征分解&#xff…

STM32 使用硬件SPI读写W25Q64芯片

STM32使用硬件SPI读写W25Q64芯片 摘要 本文详细介绍了如何使用STM32微控制器的硬件SPI接口来读写W25Q64串行Flash存储器。W25Q64是一款8Mb的SPI Flash存储器&#xff0c;广泛应用于嵌入式系统中。本文将从硬件连接、SPI初始化、W25Q64初始化、读写操作等方面进行阐述&#xf…

分析开封办理建筑工程设计资质流程

了解资质标准&#xff1a;查阅最新的建筑工程设计资质管理规定&#xff0c;明确申请所需的具体条件&#xff0c;包括注册资本、专业技术人员配备、技术装备、质量管理体系、工程业绩等要求。 组建符合资质要求的团队&#xff1a;招聘或调配具备相应资格的专业技术人员&#xf…

MySQL的复制和集群技术

MySQL的复制和集群技术是提升数据库性能、确保数据冗余和增强数据库可用性的重要手段。以下是关于MySQL复制和集群技术的详细解释&#xff1a; 1. MySQL复制&#xff08;Replication&#xff09; 1.1 定义 MySQL复制是一种将数据从一个MySQL数据库服务器&#xff08;称为主服…

【Python高级编程】Python中文本文件操作的基本方法

Python操作文本文件详解 在Python编程中&#xff0c;操作文本文件是一个非常常见的需求。无论是读取文件内容进行数据处理&#xff0c;还是将结果写入文件保存记录&#xff0c;文本文件的操作技巧都非常重要。本篇博客将详细介绍如何使用Python进行文本文件的操作&#xff0c;…

JAVA开发 选择指定的文件生成ZIP压缩包

JAVA开发 选择指定的文件生成ZIP压缩包 1、ZipOutputStream1.1 主要方法1.2 使用步骤 2、案例实现2.1 代码块2.2 运行界面 1、ZipOutputStream ZipOutputStream 是 Java 中的一个类&#xff0c;它属于 java.util.zip 包&#xff0c;用于将多个文件或数据流写入到一个 ZIP 输出…

【mysql为什么采用b+树作为索引】

## 1、Hash: 它查询任何一行数据都只需一次IO,但是只能查一行&#xff0c;不能查询范围 。 ## 2、二叉树&#xff1a; 1、 可能会单边增长&#xff0c;退化成链表&#xff0c;查询效率和没建立索引差不多。2、才二叉而已&#xff0c;树的层数太多&#xff0c;IO次数多&#x…

数据赋能(121)——体系:数据清洗——实施过程、应用特点

实施过程 数据清洗的实施过程是一个复杂而关键的任务&#xff0c;它涉及多个步骤以确保数据的准确性和一致性。以下是数据清洗通常需要进行的操作包括&#xff1a; 纠正错误&#xff1a; 识别和纠正数据中的错误&#xff0c;如拼写错误、编码错误、计算错误等。对于某些数据&…