力扣hot100-->二分查找

目录

二分查找

1. 33. 搜索旋转排序数组

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

3. 240. 搜索二维矩阵 II

3. 287. 寻找重复数


二分查找

1. 33. 搜索旋转排序数组

中等

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

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

示例 2:

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

示例 3:

输入:nums = [1], target = 0
输出:-1

提示:

  • 1 <= nums.length <= 5000
  • -104 <= nums[i] <= 104
  • nums 中的每个值都 独一无二
  • 题目数据保证 nums 在预先未知的某个下标上进行了旋转
  • -104 <= target <= 104

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left{}, right = nums.size() - 1; // 左右边界初始化

        while (left <= right) {             // 当左边界小于等于右边界时继续循环
            int mid = (left + right) / 2;   // 计算中间位置

            if (nums[mid] == target) {      // 如果找到目标值,返回索引
                return mid;
            }
            // 判断左半部分是否有序
            else if (nums[mid] >= nums[left]) {
                // 如果目标值在左半部分范围内,缩小右边界
                if (target <= nums[mid] && target >= nums[left]) {
                    right = mid - 1;
                }
                // 否则目标值在右半部分,缩小左边界
                else {
                    left = mid + 1;
                }
            }
            // 如果右半部分是有序的
            else {
                // 如果目标值在右半部分范围内,缩小左边界
                if (target >= nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                }
                // 否则目标值在左半部分,缩小右边界
                else {
                    right = mid - 1;
                }
            }
        }

        return -1; // 如果未找到目标值,返回 -1
    }
};
 

解释:

在旋转排序数组中,判断左右边界是否有序的作用是:

  1. 确定目标值可能在哪一部分。
  2. 依据部分有序性,快速缩小查找范围。
  3. 使二分查找在部分有序的条件下仍然有效。

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

中等

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

方法一:

// 二分查找
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        // 先找数组中第一个不小于target的元素
        auto left = lower_bound(nums.begin(),nums.end(),target);
        // 找数组中大于目标值的第一个元素
        auto right = upper_bound(nums.begin(),nums.end(),target);
        if(left == right) return {-1,-1};

        return {(int)(left-nums.begin()),(int)(right-nums.begin() -1)};
    }
};
 

解释:

代码解析

  1. lower_boundupper_bound 的作用

    • std::lower_bound(nums.begin(), nums.end(), target)
      • 返回指向数组中第一个 大于或等于 target 的元素的迭代器。
    • std::upper_bound(nums.begin(), nums.end(), target)
      • 返回指向数组中第一个 大于 target 的元素的迭代器。
    • 如果目标值不在数组中,lower_boundupper_bound 会返回相同的迭代器指向某个位置,因此可以用它们的比较来判断目标值是否存在。
  2. 处理目标值不在数组中的情况

    • 如果 lower_boundupper_bound 的返回值相同,说明目标值在数组中不存在,直接返回 {-1, -1}

为什么需要减去 nums.begin()

在 STL 中,lower_boundupper_bound 返回的不是数组的索引,而是指向数组元素的迭代器。如果需要将迭代器转换为整数索引,就需要计算该迭代器与起始迭代器 (nums.begin()) 之间的距离。

方法二:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        // 初始化结果为 {-1, -1},表示未找到目标值的起始和结束位置
        vector<int> result = {-1, -1};

        // 初始化左右指针,l 指向数组的起始位置,r 指向数组的末尾位置
        int l = 0, r = nums.size() - 1;

        // 开始二分查找,循环条件是左指针小于等于右指针
        while (l <= r) {
            // 计算中间位置,防止整型溢出
            int mid = l + (r - l) / 2;

            // 如果中间值小于目标值,说明目标值在右半部分,移动左指针
            if (nums[mid] < target)
                l = mid + 1;

            // 如果中间值大于目标值,说明目标值在左半部分,移动右指针
            else if (nums[mid] > target)
                r = mid - 1;

            // 如果左边界的值小于目标值,尝试向右收缩左边界
            else if (nums[l] < target)
                l++;

            // 如果右边界的值大于目标值,尝试向左收缩右边界
            else if (nums[r] > target)
                r--;

            // 如果当前左右指针的值都等于目标值,找到范围
            else {
                result[0] = l; // 起始位置为左指针的位置
                result[1] = r; // 结束位置为右指针的位置
                return result; // 直接返回结果
            }
        }

        // 如果循环结束仍未找到目标值,返回初始的 {-1, -1}
        return result;
    }
};

3. 240. 搜索二维矩阵 II

中等

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

示例 1:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -109 <= matrix[i][j] <= 109
  • 每行的所有元素从左到右升序排列
  • 每列的所有元素从上到下升序排列
  • -109 <= target <= 109

方法一:

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int rows = matrix.size();          // 矩阵的行数
        int cols = matrix[0].size();       // 矩阵的列数

        // 起始点:右上角
        int rowIndex = 0, colIndex = cols - 1;
        while (rowIndex < rows && colIndex >= 0) {
            if (target > matrix[rowIndex][colIndex]) 
                rowIndex++;                // 目标值更大,向下移动
            else if (target < matrix[rowIndex][colIndex]) 
                colIndex--;                // 目标值更小,向左移动
            else 
                return true;               // 找到目标值
        }
        return false;                      // 未找到目标值
    }
}; 

方法二:

// 二分查找
class Solution {
public:
    // 函数声明,用于在矩阵中搜索目标值
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        // 获取矩阵的行数和列数
        int m = matrix.size(), n = matrix[0].size();

        // 遍历每一行
        for(int i{}; i < m; ++i) {
            // 在当前行中使用lower_bound函数查找第一个不小于target的元素
            // lower_bound是STL中的算法,用于在已排序的序列中查找第一个不小于给定值的元素
            auto iter = lower_bound(matrix[i].begin(), matrix[i].end(), target);

            // 如果找到了且该元素等于目标值,则返回true
            if(iter != matrix[i].end() && *iter == target) return true;
        }
        // 如果遍历完所有行都没有找到目标值,则返回false
        return false;
    }
};

3. 287. 寻找重复数

中等

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

示例 1:

输入:nums = [1,3,4,2,2]
输出:2

示例 2:

输入:nums = [3,1,3,4,2]
输出:3

示例 3 :

输入:nums = [3,3,3,3,3]
输出:3

提示:

  • 1 <= n <= 105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums 中 只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size(); // 获取数组的长度
        int slow = 0, fast = 0; // 初始化两个指针,slow和fast,都指向数组的起始位置

        // 第一个循环:使用快慢指针找到相遇点,即环的某个节点
        do {
            slow = nums[slow]; // 慢指针向前移动一步
            fast = nums[nums[fast]]; // 快指针向前移动两步
        } while (slow != fast); // 如果两个指针相遇,则跳出循环

        // 重置慢指针到数组的起始位置
        slow = 0;
        // 第二个循环:再次使用快慢指针找到环的入口,即重复的元素
        while (slow != fast) {
            slow = nums[slow]; // 两个指针都从相遇点和起始位置向前移动一步
            fast = nums[fast];
        }

        // 返回找到的重复元素的值
        return slow;
    }
};

解释: 

  1. 初始化

    • slow 和 fast 都从索引 0 开始。
    • nums = [1,3,4,2,2]
  2. 第一次循环

    • slow = nums[0] = 1(索引 0 指向 1
    • fast = nums[nums[0]] = nums[1] = 3(索引 1 指向 3
    • slow = nums[1] = 3(索引 1 指向 3
    • fast = nums[nums[1]] = nums[3] = 2(索引 3 指向 2
    • slow = nums[3] = 2(索引 3 指向 2
    • fast = nums[nums[3]] = nums[2] = 4(索引 2 指向 4
    • slow = nums[2] = 4(索引 2 指向 4
    • fast = nums[nums[2]] = nums[4] = 2(索引 4 指向 2
    • 现在 slow 和 fast 在索引 2 相遇。
  3. 重置 slow

    • 将 slow 重置到索引 0
  4. 第二次循环

    • slow = nums[0] = 1(索引 0 指向 1
    • fast = nums[2] = 4(索引 2 指向 4
    • slow = nums[1] = 3(索引 1 指向 3
    • fast = nums[4] = 2(索引 4 指向 2
    • slow = nums[3] = 2(索引 3 指向 2
    • 现在 slow 和 fast 在索引 2 相遇。

由于 slowfast 在索引 2 相遇,数组中的重复元素是 nums[2] = 2。因此,输出是 2

4. 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 left = 0; // 初始化左指针为数组的开始
        int n = nums.size(); // 获取数组的长度
        int right = n - 1; // 初始化右指针为数组的末尾
        while (left <= right) { // 当左指针不大于右指针时,继续循环
            int middle = (left + right) / 2; // 计算中间位置的索引
            if (nums[middle] < target) { // 如果中间元素小于目标值
                left = middle + 1; // 调整左指针到中间位置的右侧
            } else if (nums[middle] > target) { // 如果中间元素大于目标值
                right = middle - 1; // 调整右指针到中间位置的左侧
            } else { // 如果中间元素等于目标值
                return middle; // 返回中间位置的索引,因为找到了目标值
            }
        }

        // 如果循环结束,说明目标值不在数组中,返回right + 1作为插入位置
        return right + 1;
    }
};

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

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

相关文章

南京邮电大学《智能控制技术》课后作业

一、问题一 复现二输入单输出模糊控制系统&#xff0c;改动其中一到两个环节&#xff08;隶属度设置、规则等&#xff09;&#xff0c;对比修改前后控制效果。 定义模糊 %Fuzzy Control for water tank clear all; close all;anewfis(fuzz_tank);%Fuzzy Inference System stru…

苹果ASA归因对接以及API接入

一、归因概要 广告归因&#xff0c;目的是用于衡量广告带来的激活用户的成本以及后续进一步的用户质量表现。 Apple Ads 广告平台是基于 App Store&#xff08;站内广告&#xff09;&#xff0c;同时属于自归因平台&#xff08;通常称为 SAN&#xff09;。这两个因素&#xff…

hhdb数据库介绍(9-18)

Oracle兼容性说明 数据类型兼容 本节主要介绍 HHDB Server与Oracle 数据库中数据类型的详细兼容对比信息。 比较项Oracle数据库数据类型HHDB Server数据类型对应项/替代项字符串/字符VARCHAR2( n )VARCHAR( n )字符串/字符NVARCHAR2( n )VARCHAR( n ) character set utf8字符…

服务器数据恢复—raid5阵列故障导致上层系统分区无法识别的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌DL380服务器&#xff0c;服务器中三块SAS硬盘组建了一组raid5阵列。服务器安装Windows Server操作系统&#xff0c;划分了3个分区&#xff0c;D分区存放数据库&#xff0c;E分区存放数据库备份。 服务器故障&#xff1a; RAID5阵列中有一…

STM32设计电流与温度监控python上位机监控平台设计

目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 电路图采用Altium Designer进行设计&#xff1a; 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 在现代工业自动化和智能设备管理中&#xff0c;对电流和温度的实时监控是…

STM32F103ZET6快速创建工程

1.创建工程目录,点击进目录, 然后复制目录的路径 2.双击打开kile5, 然后点击project, 创建工程 3.找到刚才的目录, 然后加入工程 4.输入芯片 STM32F103ZE, 然后保存 5.勾选对应的初始文件 6.加入main.c函数 7.双击进入Source_code文件夹 , 然后加入User,进入User 8.加入main.c文…

GIS与Web开发结合的产物:WebGIS

WebGIS&#xff0c;其实是利用Web开发技术结合地理信息系统&#xff08;GIS&#xff09;的产物&#xff0c;它是一种通过Internet实现GIS交互操作和服务的最佳途径。 WebGIS通过图形化界面直观地呈现地理信息和特定数据&#xff0c;具有可扩展性和跨平台性。 它提供交互性&am…

Python模块、迭代器与正则表达式day10

1、Python模块 1.1模块的简介 在编写代码的时候&#xff0c;创建的.py文件就被称为一个模块 1.2模块的使用 想要在a文件里使用b文件的时候&#xff0c;只要在a文件中使用关键字import导入即可 1.2.2 from ...import...语句 导入模块可以使用import&#xff0c;如果只导入模…

调用 Xinference OpenAI接口时报错 Model not found in the model list, uid

错误如下, 请不要被错误吓住或蒙蔽双眼, 自己看最下面的报错内容 Traceback (most recent call last): File "C:\Users\HW\.conda\envs\aibot\Lib\site-packages\starlette\responses.py", line 259, in __call__ await wrap(partial(self.listen_for_disconn…

小红书内容推荐算法开发:利用API打造个性化用户体验

在这个内容为王的时代&#xff0c;个性化推荐算法成为了各大平台争夺用户注意力的利器。小红书&#xff0c;作为国内领先的内容分享社区&#xff0c;其丰富的用户生成内容&#xff08;UGC&#xff09;和独特的社区氛围&#xff0c;为推荐算法的开发提供了肥沃的土壤。本文将深入…

没钱买KEGG怎么办?REACTOME开源通路更强大

之前搜集免费生物AI插图时简单提到了通路数据库Reactome&#xff08;https://reactome.org/&#xff09;&#xff0c; 那些精美的生物插图只能算是该数据库附赠的小礼品&#xff0c;他的主要功能还是作为一个开源的通路数据库&#xff0c;为相关领域的研究者提供直观的可视化生…

ChatGPT学术专用版,一键润色纠错+中英互译+批量翻译PDF

ChatGPT academic项目是由中科院团队基于ChatGPT专属定制。论文润色、语法检查、中英互译、代码解释等可一键搞定&#xff0c;堪称科研神器。 功能介绍 我们以3.5版本为例&#xff0c;ChatGPT学术版总共分为五个区域&#xff1a;输入控制区、输出对话区、基础功能区、函数插件…

版本控制【Git Bash】【Gitee】

目录 一、什么是版本控制&#xff1f; 二、版本控制的种类&#xff1a; 1、本地版本控制 2、集中版本控制 3、分布式版本控制 三、下载Git Bash 四、Git Bash 配置 五、Git Bash使用 1、切换目录&#xff1a;cd 2.查看当前文件路径&#xff1a;pwd 3.列出当前目录下文件…

关于Java合并多个Excel中的数据【该数据不是常规列表】,并入库保存的方案

1. 背景 最近在使用RPA&#xff08;机器人流程自动化&#xff09;做数据采集的时候。发现那个RPA采集&#xff0c;一次只能采集相同格式的数据&#xff0c;然后入到Excel或者库中。由于院内系统的业务限制&#xff0c;导致采集的数据是多个Excel&#xff0c;并且我们这边的需求…

【进阶系列】python的模块

模块 创建一个 .py 文件&#xff0c;这个文件就称之为 一个模块 Module 如何使用 import 想要B.py文件中&#xff0c;使用A.py文件&#xff0c;只需要在B.py文件中使用关键字import导入即可。 import A# 若A是一个包的话&#xff0c;可以这样写 import A.函数名from impor…

使用Web Workers提升JavaScript的并行处理能力

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Web Workers提升JavaScript的并行处理能力 使用Web Workers提升JavaScript的并行处理能力 使用Web Workers提升JavaScript的…

从零开始使用GOT-OCR2.0——多模态通用型OCR(非常具有潜力的开源OCR项目):项目环境安装配置 + 测试使用

在之前精读了这个多模态的OCR项目论文&#xff0c;理解了其基本的模型架构&#xff0c;论文精读地址&#xff1a; 【论文精读】GOT-OCR2.0源码论文——打破传统OCR流程的多模态视觉-语言大模型架构&#xff1a;预训练VitDet 视觉模型 阿里通义千问Qwen语言模型-CSDN博客 本文在…

【Golang】——Gin 框架中的表单处理与数据绑定

在 Web 应用开发中&#xff0c;表单是用户与服务器交互的重要手段。Gin 框架对表单处理提供了高效便捷的支持&#xff0c;包括数据绑定、验证等功能。在本篇博客中&#xff0c;我们将详细介绍如何使用 Gin 框架处理表单数据&#xff0c;涵盖基础操作与进阶技巧&#xff0c;帮助…

删除k8s 或者docker运行失败的脚本

vi delete_exited_containers.sh#!/bin/bash# 列出所有停止的容器并存储到数组 list_exited_containers() {echo -e "\nStopped containers:"containers()# 获取停止的容器信息并存入数组while IFS read -r line; docontainers("$line")done < <(do…

Linux(命令格式详细+字符集 图片+大白话)

后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 在这里真的很感谢这位老师的教学视频让迷茫的我找到了很好的学习视频 王晓春老师的个人空间…