一. 简介

上一篇文章对力扣网上"有序数组中查找目标值范围"题目进行了普通的解法。文章如下:

力扣网C语言编程题:在数组中查找目标值位置之暴力解法-CSDN博客

本文使用二分查找法进行实现,因为二分查找法符合题目要求(时间复杂度为 O(log n))。

二.  力扣网C语言编程题:在数组中查找目标值位置之二分查找法

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

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

1. 解题思路二:(二分查找法)

题目说数组是非递减序列,也就是说数组元素从左到右元素是不严格递增的,即每个元素大于或等于前一个元素。有序序列中查找一个目标值,符合 "二分查找法" 的特点。

首先,查找target 第一次出现的位置,并记录下来;

其次,查找target最后一次出现的位置,并记录下来;

C语言实现如下:

//二分查找法
int* searchRange(int* nums, int numsSize, int target, int* returnSize){int* ret_ptr = (int*)malloc(2*sizeof(int));ret_ptr[0] = -1;ret_ptr[1] = -1;if((nums == NULL) || (numsSize <= 0) || (returnSize == NULL)) {return ret_ptr;}*returnSize = 2;//查找第一次出现的位置int left = 0;int right = numsSize-1;int mid = 0;while(left <= right) {mid = (left+right) / 2;if(nums[mid] >= target) {//向左收缩区间right = mid - 1;}else { //nums[mid] < target, 向右收缩区间left = mid + 1;}}//需要额外判断是否真的找到了targetif((left < numsSize) && (nums[left] == target)) {ret_ptr[0] = left;}else{return ret_ptr;}//查找最后一次出现的位置right = numsSize-1;while(left <= right) {mid = (left + right) / 2;if(nums[mid] <= target) {//向右收缩区间left = mid + 1;}else {//nums[mid] > target,向左收缩区间right = mid - 1;}}ret_ptr[1] = right;return ret_ptr;
}

(1) 查找目标值 target 第一次出现的位置的实现思路?

目标:

找到第一个等于 target 的索引。换句话说,我们要找到最小的下标 i,使得 nums[i] == target。

理解逻辑的关键点

注意: 这段二分查找不是寻找 “等于”,而是不断缩小范围,直到 left 指向第一个满足条件的元素。

思路拆解:

    我们始终维护一个区间 [left, right],表示目标值可能在这个区间内。
    如果 nums[mid] < target:说明要找的目标在右边,于是 left = mid + 1
    如果 nums[mid] >= target:说明目标可能在左边或当前位置,于是 right = mid - 1

    注意:即使 nums[mid] == target,我们也继续往左找,看看有没有更早的相同值。

循环结束时的状态:

当 while (left <= right) 跳出循环时,right < left,此时 left 是第一个大于等于 target 的位置。
如果 target 存在于数组中,那么 left 正好指向它第一次出现的位置。

(2) 查找目标值 target 最后一次出现的位置的实现思路?

目标:

我们要找到 最后一个等于 target 的位置。换句话说,我们要找到最大的下标 i,使得 nums[i] == target。

核心思想:

我们仍然使用二分查找,但这次不是找第一个大于等于 target 的位置,而是:

    如果 nums[mid] <= target,说明可能还有更大的、也等于 target 的位置在右边 → 向右缩
    如果 nums[mid] > target,说明当前点和右边都太大了 → 向左缩

思路拆解:

    我们始终维护一个区间 [left, right],表示目标值可能在这个区间内。
    当 nums[mid] <= target 时,我们尝试往右找是否有更靠后的相同值。
    即使 nums[mid] == target,我们也继续向右搜索,看有没有更多相同的值。

这样,随着循环不断进行,left 最终会停在 最后一个 target 的下一个位置,所以最终的位置是 right。

循环结束时的状态:

当 while (left <= right) 跳出循环时,left > right,此时:

    right 是最后一个 ≤ target 的位置。
    如果 nums[right] == target,那它就是最后一次出现的位置。

三. 总结:

问题

回答

为什么跳出循环后 left 是第一个 target 出现的位置?

因为我们使用的是 “左缩” 策略,最终 left 停在第一个 ≥ target 的位置,如果存在 target,那这个位置就是它的首次出现。

为什么跳出循环后 right 是最后一个 target 出现的位置?

因为我们使用的是 “右缩” 策略,最终 right 停在最后一个 ≤ target 的位置,如果存在 target,那这个位置就是它的最后一次出现。

时间复杂度是多少?

O(log n)

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

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

相关文章

前端查询条件加密传输方案(SM2加解密)

一、需求背景 控台项目甲方进行安全测试&#xff0c;测试报告其中一条&#xff1a;敏感信息明文传输 1 敏感信息明文传输 中危 查询接口传输手机号、银行卡号等敏感信息时未加密/脱敏处理。 二、解决方案 讨论出的方案是通过前端查询条件加密&#xff0c;后端对加密的…

【Python】Flask网页

Flask第三方库安装命令&#xff1a;pip install flask代码&#xff1a;from flask import Flask app Flask(__name__)app.route("/") def hello():return "Hello world!"if __name__ "__main__":app.run()其中的"Hello world!"可以改…

数字资产革命中的信任之锚:RWA法律架构的隐形密码

首席数据官高鹏团队律师创作&#xff0c;AI辅助 在数字经济的浪潮中&#xff0c;资产的边界正在被重新定义。当一块地产、一笔应收账款、甚至一份碳配额被转化为链上的数字代币时&#xff0c;技术的光芒固然耀眼&#xff0c;但真正决定其生命力的&#xff0c;是背后隐匿的“信…

mobaxterm终端sqlplus乱码问题解决

背景。使用mobaxterm终端连接linux。在查询数据库表注释时发现**&#xff1f;**中文乱码。影响对表的分析。完成以下三个编码设置再打开sqlplus查询含中文的数据就正常了 总结。需要查看sqlplus的编码是什么 SELECT parameter, value FROM nls_database_parameters WHERE pa…

一个简单的分布式追踪系统

1. 准备工作 导入必要的库 import contextvars import time from typing import Any, Optional, Dict, List, Union from dataclasses import dataclass, field2. 定义上下文变量 # 定义两个上下文变量&#xff0c;存储当前 Span 和 Trace _current_span: contextvars.Conte…

【Qt】事件处理、事件分发器、事件过滤器

事件处理 一. 事件事件处理鼠标事件处理按键事件处理定时器事件处理窗口事件处理 二. 事件分发器三. 事件过滤器 虽然 Qt 是跨平台的 C 开发框架&#xff0c;Qt 的很多能力其实是操作系统提供的&#xff0c;只不过 Qt 封装了系统 API&#xff0c;程序是运行在操作系统上的&…

广东省省考备考(第三十八天7.4)——言语理解:逻辑填空(题目训练)

错题解析 本题可从第二空入手&#xff0c;横线处搭配“理论”&#xff0c;且根据“使得”可知&#xff0c;横线处与前文构成因果关系&#xff0c;即“遗传学的空白和古生物证据的缺乏”导致他的理论在某些方面存在不足&#xff0c;A项“捉襟见肘”指拉一拉衣襟&#xff0c;就露…

5G网络切片技术

5G中的网络切片技术是一种通过虚拟化将单一物理网络划分为多个独立、可定制的虚拟网络的技术&#xff0c;旨在满足不同应用场景对网络性能、带宽、时延等需求的差异化要求。以下从技术原理、核心价值、应用场景、实现方式及未来趋势五个维度展开分析&#xff1a;一、技术原理&a…

算法学习笔记:7.Dijkstra 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学领域&#xff0c;图论算法一直占据着重要地位&#xff0c;其中 Dijkstra 算法作为求解单源最短路径问题的经典算法&#xff0c;被广泛应用于路径规划、网络路由等多个场景。无论是算法竞赛、实际项目开发&#xff0c;还是计算机考研 408 的备考&#xff0c;Dijkstr…

汇编 函数调用栈

前言 网上很多对函数栈的解释&#xff0c;说的不是很清楚感觉&#xff0c;尤其是对到底是谁的栈&#xff0c;以及指令的微小但是很致命的细节没说&#xff0c;特写本文&#xff0c;一是帮助自己记忆&#xff0c;二是为了帮助大家&#xff0c;如有疏忽错误请指正。 核心概念 首先…

基于Apache MINA SSHD配置及应用

Apache MINA SSHD 是一个基于 Java 的 SSH 服务器和客户端实现&#xff0c;它是 Apache MINA 项目的一部分&#xff0c;提供了完整的 SSH 协议支持。 主要特性 SSH 协议支持&#xff1a; 支持 SSH2 协议 兼容大多数 SSH 客户端 支持多种加密算法和密钥交换方法 服务器功能…

Excel 如何让数据自动按要求排序或筛选?

让数据按要求排序和筛选是Excel数据处理的基础核心功能&#xff0c;也是进行有效分析前必做的准备工作。下面我们分开讲解这两个功能。 一、排序 (Sort)&#xff1a;让数据井井有条 排序的目的是重新排列数据行的顺序&#xff0c;以便更好地观察和比较。 1. 快速单列排序 (最…

Django 安装使用教程

一、Django 简介 Django 是一个高级 Python Web 框架&#xff0c;鼓励快速开发和简洁实用的设计。它内置 ORM、认证系统、后台管理、表单处理、路由控制等功能&#xff0c;广泛用于开发企业级网站、内容管理系统、电商平台等。 二、环境准备 2.1 安装 Python Django 基于 Py…

前沿交叉:Fluent与深度学习驱动的流体力学计算体系

基础模块 流体力学方程求解 1、不可压缩N-S方程数值解法&#xff08;有限差分/有限元/伪谱法&#xff09; Fluent工业级应用&#xff1a;稳态/瞬态流、两相流仿真&#xff08;圆柱绕流、入水问题&#xff09; Tecplot流场可视化与数据导出 2、CFD数据的AI预处理 基于P…

五、Flutter动画

目录1. Flutter 中动画的基本概念是什么&#xff1f;2. 解释 AnimationController 和 Tween 的作用3. 如何实现一个补间&#xff08;Tween&#xff09;动画&#xff1f;4. 什么是隐式动画&#xff1f;举例说明5. 如何实现自定义复杂动画&#xff1f;1. Flutter 中动画的基本概念…

全网唯一/Qt结合ffmpeg实现手机端采集摄像头推流到rtsp或rtmp/可切换前置后置摄像头/指定分辨率帧率

一、前言说明 之前已经实现了Qt结合ffmpeg在安卓上运行&#xff0c;所有在win上的功能&#xff0c;在安卓上都已经实现&#xff0c;比如编码保存到MP4文件&#xff0c;正常解码音视频文件播放等&#xff0c;唯独还差一个功能&#xff0c;尽管用的不多&#xff0c;但是还是有一…

Install Ubuntu 24.04 System

1.制作安装镜像盘&#xff08;U盘&#xff09; 下载rufus制作工具(网址&#xff1a;https://www.xiaomoxz.com/nexus/bi1/rufus4.shtml?bd_vid8643969197265870719&#xff09; 2. 设置U盘启动&#xff1a; F2进入BIOS 3. Install Ubuntu 24.04 Ubuntu下载地址&#xff1a;…

solidjs 处理复杂类型的响应式

solidjs 处理复杂类型的响应式 在 solidjs 里响应式一般直接用 createSignal 就可以&#xff0c;但 createSignal 一般用于基础数据类型。 虽然复杂类型也是可以使用&#xff0c;但基于起细粒度响应性的特性。 一般复杂的数据使用 createSignal 就不是那么友好了。 所以 cre…

爬虫技术-获取浏览器身份认证信息(如 Cookie、Token、Session 等)

方法一&#xff1a;通过浏览器开发者工具查看和提取 Cookie / Token &#x1f4cc; 示例场景&#xff1a; 你在使用一个网站时已经登录了&#xff0c;想看看这个网站是如何保存你的身份凭证的。 &#x1f527; 操作过程&#xff1a; 打开浏览器&#xff08;例如 Chrome&#xf…

[密码学实战]GMT 0136-2024《密码应用HTTP接口规范》解析

[密码学实战]GM/T 0136-2024《密码应用HTTP接口规范》解析国家密码管理局于2025年7月1日正式实施GM/T 0136-2024标准&#xff0c;该规范首次统一了密码服务的HTTP接口设计&#xff0c;为国产密码技术的规模化应用铺平道路。本文结合标准原文&#xff0c;深入剖析其技术细节并给…