题目

给你一个按照非递减顺序排列的整数数组 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]

解析

问:如何理解 end = lowerBound(nums, target + 1) - 1 这段代码?

答:要想找到 ≤target 的最后一个数,无需单独再写一个二分。我们可以先找到这个数的右边相邻数字,也就是 >target 的第一个数。在所有数都是整数的前提下,>target 等价于 ≥target+1,这样就可以复用我们已经写好的二分函数了,即 lowerBound(nums, target + 1),算出这个数的下标后,将其减一,就得到 ≤target 的最后一个数的下标。

问:如果 ≥target+1 的第一个数不存在怎么办?

答:这说明数组中的数都 ≤target。如果数组中有 target,那么数组的最后一个数(下标 n−1)就是 target(因为数组是递增的)。同时,lowerBound(nums, target + 1) 在这种情况下会返回 n,减一得到 n−1,这正是我们要计算的下标。

问:为什么要写 left + (right - left) / 2?

答:在面试或者实际场景中,你不一定知道输入的数组有多长,万一数组长度达到 int 最大值,left + right 可能会发生加法溢出。当然,如果只看本题的数据范围,写 (left + right) / 2 也可以。对于 Python 来说,由于没有溢出这个概念,所以可以直接相加。

问:怎么判断我写的是哪一种二分?

答:看 while 循环的条件,如果是 left <= right,就是闭区间;如果是 left < right,就是半闭半开区间;如果是 left + 1 < right,就是开区间。

问:对于闭区间写法,为什么 nums[mid] >= target 的时候要写 right = mid - 1?此时的 mid 不是有可能是答案吗?这样写不会错过答案吗?

答:答案在区间外面,不在区间里面。如果觉得答案在区间里面的话,请思考这个问题:闭区间循环结束后 left>right,区间 [left,right] 是空的,什么也没有,难道答案在空区间里面吗?

问:我看到一种二分的写法,在二分的过程中,额外记录答案的值,你对此怎么看?

答:喜欢这种写法的同学,推荐写开区间二分,因为开区间二分 if 条件成立时更新的是哪个变量,最后返回的也就是哪个变量。这和记录答案的做法如出一辙。

问:关于开区间二分,如何理解 −1 和 n 这两个下标?

答:可以假设 nums[−1]=−∞ 以及 nums[n]=∞,此时 nums 仍然是有序的。在这种情况下,nums[−1]<target,所以 −1 是红色;nums[n]≥target,所以 n 是蓝色。

作者:灵茶山艾府
链接:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/solutions/1980196/er-fen-cha-zhao-zong-shi-xie-bu-dui-yi-g-t9l9/
来源:力扣(LeetCode)

答案

class Solution:# lower_bound 返回最小的满足 nums[i] >= target 的下标 i# 如果数组为空,或者所有数都 < target,则返回 len(nums)# 要求 nums 是非递减的,即 nums[i] <= nums[i + 1]def lower_bound(self, nums: List[int], target: int) -> int:left, right = -1, len(nums)  # 开区间 (left, right)while left + 1 < right:  # 区间不为空mid = (left + right) // 2# 循环不变量:# nums[left] < target# nums[right] >= targetif nums[mid] >= target:right = mid  # 范围缩小到 (left, mid)else:left = mid  # 范围缩小到 (mid, right)# 循环结束后 left+1 = right# 此时 nums[left] < target 而 nums[right] >= target# 所以 right 就是第一个 >= target 的元素下标return rightdef searchRange(self, nums: List[int], target: int) -> List[int]:start = self.lower_bound(nums, target)  # 选择其中一种写法即可if start == len(nums) or nums[start] != target:return [-1, -1]  # nums 中没有 target# 如果 start 存在,那么 end 必定存在end = self.lower_bound(nums, target + 1) - 1return [start, end]# 作者:灵茶山艾府
# 链接:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/solutions/1980196/er-fen-cha-zhao-zong-shi-xie-bu-dui-yi-g-t9l9/
# 来源:力扣(LeetCode)

复杂度分析

时间复杂度:O(logn),其中 n 为 nums 的长度。

空间复杂度:O(1),仅用到若干额外变量。

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

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

相关文章

自建知识库,向量数据库 (十二)之 文章向量搜索——仙盟创梦IDE

“未来之窗” 文章向量搜索&#xff1a;多领域应用与学习指南 在数字化浪潮中&#xff0c;“未来之窗” 文章向量搜索凭借其独特的技术优势&#xff0c;在酒店、电商、诊疗及知识库等多个领域展现出巨大的应用潜力&#xff0c;为各行业的信息处理与检索带来了全新的视角和高效…

深度剖析:基于反射的.NET二进制序列化器设计与实现

&#x1f50d; 深度剖析&#xff1a;基于反射的.NET二进制序列化器设计与实现本文将从底层原理到高级优化&#xff0c;全面剖析一个基于反射的.NET二进制序列化器的设计与实现&#xff0c;涵盖类型系统处理、内存布局、递归算法、性能优化等核心主题。1. 设计哲学与架构总览 1.…

如何在 Ubuntu 上安装和配置 Samba ?

Samba 是一个开源程序&#xff0c;用于文件共享和网络打印&#xff0c;使用 SMB 协议。现在基本上用于提供在 Windows 上可访问的 Linux 文件共享系统。 本文介绍如何在 Ubuntu 上安装和配置 Samba 服务器&#xff0c;以便跨文件夹共享网络上不同的计算机。 Update Your Syst…

MATLAB实现CNN-GRU-Attention时序和空间特征结合-融合注意力机制混合神经网络模型的风速预测

该 MATLAB 代码实现了一个基于 CNN-GRU-Attention 时序和空间特征结合-融合注意力机制混合神经网络模型的风速预测。以下是对代码的简要分析&#xff1a;一、主要功能 该代码用于风速时间序列预测&#xff0c;使用历史风速特征数据&#xff08;18个特征&#xff0c;75天&#x…

【升级版】从零到一训练一个 0.6B 的 MoE 大语言模型

前文&#xff1a;从零到一训练一个 0.6B 的 MoE 大语言模型&#xff0c;本次升级完全重新从零开始重新训练。主要升级如下&#xff1a; 替换预训练数据集&#xff0c;使用序列猴子通用文本数据集进行预训练。使用更先进的训练方法。新增思考模式控制&#xff0c;可通过添加/th…

51单片机-实现定时器模块教程

本章概述思维导图&#xff1a; 51单片机驱动定时器模块 CPU时序简介 CPU时序定义了CPU内部操作的时间节奏&#xff0c;以下从四个时序周期进行逐步解析&#xff1b; 1、振荡周期 振荡周期&#xff1a;CPU内部时钟源产生的最小时间单位&#xff0c;由晶振或内部振荡器决定&am…

7.Kotlin的日期类

以下是 Kotlin 中常用时间类&#xff08;基于 java.time 包&#xff09;的核心方法及使用示例&#xff0c;参考数组方法的表格形式&#xff0c;按类分类展示&#xff1a; 一、LocalDate&#xff08;日期&#xff1a;年/月/日&#xff09;方法签名返回值说明示例now(): LocalDat…

【Big Data】Hive技术解析:大数据仓库的SQL桥梁

Hive作为Apache顶级项目&#xff0c;是Hadoop生态系统中最具影响力的SQL查询引擎&#xff0c;它解决了大数据处理与传统SQL技能之间的鸿沟。Hive的核心价值在于将类SQL查询语言HiveQL无缝转换为分布式计算框架MapReduce的任务&#xff0c;使数据分析师能够利用熟悉的SQL语法操作…

Ubuntu2204server系统安装postgresql14并配置密码远程连接

前言&#xff1a; 最近因项目需要安装postgresql14&#xff0c;系统是ubuntu2204server系统&#xff0c;安装好后发现无法实现远程连接&#xff0c;解决了之后在此记录一下解决方法。 疑问&#xff1a; 什么情况下需要配置postgresql远程连接&#xff1f; ①如果是postgresql和…

【嵌入式】【搜集】状态机、状态迁移图及状态模式材料

文章目录状态机状态机状态机定义与核心特点状态机总结状态迁移图状态迁移图状态迁移图核心概念与要素状态迁移图常见错误与规避状态迁移图总结状态模式状态模式状态模式核心概念与组成状态模式核心价值与适用场景状态模式优缺点分析进阶优化技巧行为模式总结状态机 状态机 状…

Java学习历程14——制作一款五子棋游戏(4)

上次我们基本实现了五子棋游戏的功能&#xff0c;这次我们进行一些优化和添加一些便于用户使用的功能。新增功能及优化一、复盘功能复盘功能就是指在下完一局棋后&#xff0c;我们可以通过复盘按钮使本局棋的所有棋子重头开始自动下一遍。分析得知&#xff0c;我们首先要保存以…

记录一次el-table+sortablejs的拖拽bug

bug回顾出现bug的情况时 当编辑表格过于紧凑的时候 有些非必要编辑或需要一眼看到的数据 移动到了el-table-column typeexpand时 同事&#xff1a;怎么拖拽功能用不了了 ok开始检查代码 当原来是个简单的编辑表格 不涉及展开和简单拖拽时 不会出现问题 解决了 出现了展开行以后…

利用go sort.Sort()排序自定义切片

1 sort.Sort()简介2 核心功能3 调用前提4 代码示例 1 sort.Sort()简介 Go语言中的sort.Sort函数是标准库提供的通用排序接口 2 核心功能 核心功能支持多种类型进行快速排序 基础类型支持‌&#xff1a;内置Ints、Float64s、Strings等函数直接排序常见切片 自定义排序‌&a…

Elasticsearch脑裂紧急处理与预防

在 Elasticsearch 中出现 网络分区&#xff08;Network Partition&#xff09; 或 脑裂&#xff08;Split-Brain&#xff09; 导致两个子集群各自选出 Master 的情况&#xff0c;是非常严重的问题。比如这个场景&#xff08;20个节点分裂成两个10节点的子集群&#xff0c;各自选…

华为网路设备学习-29(BGP协议 四)路由策略-实验

示例 延伸-具体实验1.代码部分&#xff1a;基础配置R1 [Huawei]int GigabitEthernet 0/0/0 [Huawei-GigabitEthernet0/0/0]ip address 10.1.13.1 24[Huawei]int LoopBack 1 [Huawei-LoopBack1]ip address 172.16.1.1 24 [Huawei-LoopBack1]q [Huawei]int LoopBack 2 [Huawei-Lo…

500系列状态码与可能的场景

501 Not Implemented&#xff08;未实现&#xff09;HTTP 方法不支持客户端发送了 PUT、DELETE、PATCH 请求但服务器只实现了 GET 和 POST协议功能不支持客户端使用了 HTTP/2 的某些高级特性服务器只支持 HTTP/1.1&#xff0c;无法处理&#xff0c;返回 501API 接口未完成开发中…

大数据、hadoop、爬虫、spark项目开发设计之基于数据挖掘的交通流量分析研究

大数据、hadoop、爬虫、spark项目开发设计之基于数据挖掘的交通流量分析研究

Pytest项目_day20(log日志)

Log日志优点&#xff1a;记录程序运行信息&#xff0c;方便定位问题python日志模块logging&#xff0c;日志等级如下&#xff1a; DEBUGINFO&#xff08;正常&#xff09;WARNINGERROR&#xff08;报错&#xff09;示例代码如下&#xff1a;import logging import os.path impo…

elasticsearch中的分词器配置及使用

一、什么是分词器&#xff1f; 在 Elasticsearch&#xff08;ES&#xff09;中&#xff0c;分词器&#xff08;Analyzer&#xff09; 是处理文本的核心组件&#xff0c;负责将原始文本转换为可搜索的索引词&#xff08;Term&#xff09;。它是文本分析过程的核心&#xff0c;直…

《Linux 网络编程二:UDP 与 TCP 的差异、应用及问题应对》

一、UDP 与 TCP 对比表对比项UDPTCP连接方式无需建立连接有连接&#xff08;三次握手建立&#xff0c;四次挥手断开&#xff09;传输可靠性尽最大努力交付&#xff0c;可能丢包安全可靠的数据传输机制面向对象面向数据包面向数据流传输模式一对一、一对多传输本质一对一&#x…