LeetCode 第34题:二分查找+扩展搜索

news2025/1/9 11:04:44

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

LeetCode 第34题要求在一个排序的数组中找到给定目标值的第一个和最后一个位置。如果目标值不存在,则返回 [-1, -1]。在本篇文章中,我将为大家提供详细的 C 语言解法,并逐行解释代码。

题目分析

给定一个升序排列的整数数组 nums 和一个目标值 target,我们需要找到目标值 target 在数组中首次和最后一次出现的位置。如果数组中没有目标值,则返回 [-1, -1]

解法思路

我们可以使用二分查找来加速搜索过程,利用排序数组的性质找到目标值的第一个和最后一个位置。

具体的思路如下:

  1. 使用二分查找找到目标值的位置。
  2. 找到目标值后,通过向左扩展和向右扩展的方式来确定目标值的最左和最右位置。
  3. 如果找不到目标值,返回 [-1, -1]

代码实现

代码解读

#include <stdio.h>
#include <stdlib.h>

/**
 * searchRange 函数用于在已排序的数组中找到目标值的起始和结束位置。
 * 如果目标值不存在,则返回 [-1, -1]。
 * 
 * @param nums: 排序后的整数数组。
 * @param numsSize: 数组的大小。
 * @param target: 要查找的目标值。
 * @param returnSize: 返回数组的大小,固定为2,表示包含目标值的范围。
 * @return: 一个包含目标值范围的数组,范围为 [left, right],如果目标值不存在返回 [-1, -1]。
 */
int* searchRange(int* nums, int numsSize, int target, int* returnSize) {
    // 设置返回数组的大小为2,表示结果为目标值的起始和结束位置
    *returnSize = 2;

    // 动态分配结果数组,用于存储目标值的起始和结束位置
    int* result = (int*)malloc(sizeof(int) * 2);
    
    // 检查内存分配是否成功
    if (result == NULL) {
        *returnSize = 0;  // 如果内存分配失败,返回0大小的数组
        return NULL;
    }

    // 初始化结果数组,默认值为 [-1, -1]
    result[0] = -1;
    result[1] = -1;

    // 如果数组为空或目标值不在数组的范围内,直接返回 [-1, -1]
    if (numsSize == 0 || nums[0] > target || nums[numsSize - 1] < target) {
        return result;
    }

    int left = 0;            // 左指针
    int right = numsSize - 1;  // 右指针
    int middle = 0;          // 中间指针

    // 二分查找目标值的位置
    while (left <= right) {
        middle = left + (right - left) / 2;  // 计算中间位置,避免溢出
        if (nums[middle] == target) {  // 找到目标值
            // 找到目标值后,向左和向右扩展,找到最左和最右的目标值
            int m_left = middle;
            int m_right = middle;

            // 向右扩展,直到不再等于目标值
            while ((m_right + 1) < numsSize && nums[m_right + 1] == target) {
                m_right += 1;
            }

            // 向左扩展,直到不再等于目标值
            while ((m_left - 1) >= 0 && nums[m_left - 1] == target) {
                m_left -= 1;
            }

            // 设置结果数组,返回最左和最右位置
            result[0] = m_left;
            result[1] = m_right;
            return result;
        }

        // 根据中间值与目标值的大小关系调整左右指针
        if (nums[middle] > target) {
            right = middle - 1;  // 如果目标值小于中间值,右指针左移
        } else {
            left = middle + 1;  // 如果目标值大于中间值,左指针右移
        }
    }

    // 如果没有找到目标值,返回 [-1, -1]
    return result;
}

int main() {
    // 示例数组和目标值
    int nums[] = {5, 7, 7, 8, 8, 10};
    int target = 8;
    int returnSize;
    


    // 调用 searchRange 函数
    int* result = searchRange(nums, sizeof(nums) / sizeof(nums[0]), target, &returnSize);

    // 输出结果
    if (result != NULL) {
        printf("Range: [%d, %d]\n", result[0], result[1]);
        free(result);  // 记得释放动态分配的内存
    } else {
        printf("Target not found.\n");
    }

    return 0;
}

代码分析

  1. 初始化和内存分配:我们首先动态分配了一个 result 数组,用于存储目标值的最左和最右位置。若内存分配失败,我们将 returnSize 设置为 0 并返回 NULL

  2. 边界检查:在开始二分查找之前,我们进行了边界检查。如果目标值不可能出现在数组中(如目标值小于数组中的最小值或大于数组中的最大值),我们直接返回 [-1, -1]

  3. 二分查找:我们通过 while 循环进行二分查找,在找到目标值后,进一步扩展搜索范围,找到目标值的最左和最右位置。

  4. 结果输出:最后,我们通过 printf 输出目标值的范围。如果目标值不存在,我们输出 “Target not found”。

时间复杂度分析

  • 二分查找 的时间复杂度是 O(log n),在最坏情况下,我们只需要进行一次二分查找。
  • 扩展查找最左和最右位置的过程是线性的 O(n),但这仅在找到目标值后进行,所以整体时间复杂度仍然是 O(n)。

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

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

相关文章

【江协STM32】9-1/2/3 USART串口协议、USART外设、串口发送串口发送+接收

1. 通信接口 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发全双工&#xff1a;指通信双方能够同时进行双向通信。发送线路和接收线路互不影响&#xff0c…

小程序租赁系统开发的优势与应用前景分析

内容概要 小程序租赁系统是一种新兴的数字化解决方案&#xff0c;旨在为用户提供更加便捷与高效的租赁服务。它通常包括一系列功能&#xff0c;如在线浏览、即时预定、支付功能以及用户反馈机制。这些系统在使用上极为友好&#xff0c;让用户能够轻松选择所需的商品或服务&…

25/1/8 算法笔记<强化学习> GYM环境

前几天花了好多时间在装各个仿真环境上&#xff0c;有V-rep,Pybullet,unity的Ml-agent,很多一大堆&#xff0c;好多好多问题差点逼疯我&#xff0c;可能就pybullet能玩一点&#xff0c;到之后学了机器人我再来玩它&#xff0c;最后的最后&#xff0c;我发现还得是我的gym&#…

学习随记:word2vec中归一化处理的作用

答案来自ai&#xff0c;直接复用为参考&#xff1a; 向量归一化的好处 将向量进行归一化&#xff0c;使其模长为 1&#xff08;即投射到单位圆/单位球上&#xff09;&#xff0c;在许多情况下具有实际意义和计算优势。以下是归一化的主要好处和原因&#xff1a; 1. 提高数值稳…

【C++】B2108 图像模糊处理

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述题目内容输入格式输出格式示例输入&#xff1a;输出&#xff1a; &#x1f4af;题目分析问题拆解 &#x1f4af;我的做法代码实现代码分析 &#x1f4af;老师的做法…

selenium+pyqt5自动化工具总结

说明&#xff1a;本工具是&#xff0c;操作外部google浏览器、selenium是无法操作qt界面中嵌套的浏览器的&#xff0c; 工具在后面 1. 代码结构 pycharm打开的文件下&#xff0c;再写一个子文件&#xff0c;文件导入的时候把子文件名带上 这样就可以在 外层使用命令 pyinst…

经典多模态模型CLIP - 直观且详尽的解释

对比语言-图像预训练&#xff08;CLIP&#xff09;&#xff0c;这是一种创新的多模态建模策略&#xff0c;能够创建视觉和语言的联合表示。CLIP 的效果非常出色&#xff0c;可以用于构建高度特定且性能卓越的分类器&#xff0c;而无需任何训练数据。本文将深入探讨其理论基础&a…

新时期下k8s 网络插件calico 安装

1、k8s master节点初始化完毕以后一直处于notreadey状态&#xff0c;一直怀疑是安装有问题或者是初始化有问题&#xff08;当然&#xff0c;如果真有问题要先解决这些问题&#xff09;&#xff0c;经过不断探索才发现是网络插件没有安装导致的&#xff0c;根据建议安装calico插…

【图像加密解密】Logistic混沌映射的彩色图像加密算法复现(含相关性检验)【Matlab完整源码 1期】

1、说明 本文给出详细完整代码、完整的实验报告和PPT。 环境&#xff1a;MATLAB2019a 复现文献&#xff1a;[1]黄硕.基于改进的Logistic混沌映射彩色图像加密算法[J].河南工程学院学报(自然科学版),2015,27(02):63-67. 主要目的是为了快速了解何为混沌序列、混沌序列产生、…

[AUTOSAR 基础入门] - RTE虚拟总线详解

文章目录 一、什么是RTE二、RTE的作用三、RTE对Runnables的运行支撑四、RTE与通信4.1. RTE – ECU之间通信4.2. RTE - Sender/Receiver 通信4.2.1 不使用队列&#xff08;直接访问&#xff09;4.2.2 不使用队列&#xff08;缓存访问&#xff09;4.2.3 使用队列 4.3 RTE - Clien…

Linux下文件操作相关接口

文章目录 一 文件是什么普通数据文件 二 文件是谁打开的进程用户 三 进程打开文件的相关的接口c语言标准库相关文件接口1. fopen 函数2. fread 函数3. fwrite 函数4. fclose 函数5. fseek 函数 linux系统调用接口1. open 系统调用2. creat 系统调用3. read 系统调用4. write 系…

用Python实现简单的任务自动化

目录 1. 自动发送邮件提醒 2. 自动备份文件 3. 自动下载网页内容 总结 在现代工作和生活中,任务自动化可以极大地提高效率和准确性。Python,作为一种功能强大且易于学习的编程语言,是实现任务自动化的理想选择。本文将通过几个简单而实用的案例,展示如何用Python实现任…

小程序开发-页面事件之上拉触底实战案例

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

Docker 服务、镜像、容器之命令(Docker Services, Images, and Container Commands)

Docker 服务、镜像、容器之命令 Docker是一个强大的容器化平台&#xff0c;能够帮助开发者高效地构建、部署和管理应用程序。本文将详细介绍Docker的服务命令、镜像命令和容器命令&#xff0c;帮助你快速上手Docker。 一、Docker的服务相关命令 在使用Docker之前&#xff0c…

STM32内置Flash

一、原理 利用flash存储用户数据需要注意查看&#xff0c;用户数据是否会覆盖芯片运行程序。 IAP&#xff08;在程序中编程&#xff09;利用程序修改程序本身&#xff0c;和OTA是一个原理。IAP在程序中编程支持任意一种通信下载。 ICP&#xff08;在电路中编程&#xff0c;通…

两种方式实现Kepware与PLC之间的心跳检测

两种方式实现Kepware与PLC之间的心跳检测 实现Kepware与PLC之间的心跳检测1.OPCUA 外挂程序2.Kepware Advanced Tag 实现Kepware与PLC之间的心跳检测 1.OPCUA 外挂程序 这是通过上位程序来触发心跳的一种机制&#xff0c;在C#中&#xff0c;可以利用OPC UAOPCAutodll的方式…

英伟达Project Digits赋能医疗大模型:创新应用与未来展望

英伟达Project Digits赋能医疗大模型&#xff1a;创新应用与未来展望 一、引言 1.1 研究背景与意义 在当今数字化时代&#xff0c;医疗行业作为关乎国计民生的关键领域&#xff0c;正面临着前所未有的挑战与机遇。一方面&#xff0c;传统医疗模式在应对海量医疗数据的处理、复…

中国省级产业结构高级化及合理化数据测算(2000-2023年)

一、数据介绍 数据名称&#xff1a;中国省级产业结构高级化、泰尔指数 数据年份&#xff1a;2000-2023年 数据范围&#xff1a;31个省份 数据来源&#xff1a;中国统计年鉴、国家统计局 数据整理&#xff1a;内含原始版本、线性插值版本、ARIMA填补版本 数据说明&#xf…

关于Mac使用VSCode连接虚拟机

1. 下载插件 输入Remote - SSH下载下图两个插件。 2. 配置虚拟机信息 按图示步骤点击完成后&#xff0c;进入到虚拟主机的配置页面。 其中Host可以自定义主机名&#xff0c;HostName是虚拟机ip&#xff0c;可以通过ifconfig eth0查看ip&#xff0c;User是虚拟机的用户名。…

GOGOGO 接口

低高耦合?【程序中追求低耦合,所以接口广用】 低耦合:关联依赖性弱(你走了我还在) 高耦合:关联依赖性强(牵一发而动全身) 接口 概念:多个抽象方法的集合,只有结构无具体实现,并交给实现类完成功能操作【接口写功能,实现类写具体实现】 语法结构: 定义接口的关…