hot100 -- 二分查找

目录

前言

🎂搜索插入位置

🌼搜索二维矩阵

🌼排序数组元素第一和最后一个位置

🌼旋转排序数组

💪旋转排序数组中的最小值

💪两个正序数组的中位数


前言

二分算法学习_时间超限ac:0%-CSDN博客

🎂搜索插入位置

35. 搜索插入位置 - 力扣(LeetCode)

直接套博客里的万能模板不太行,万能模板只能处理下取整死循环的问题,但是本题:

目标值 target 不一定在数组里

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while (l <= r) {
            int m = (l + r) >> 1;
            if (target > nums[m])
                l = m + 1;
            else if (target < nums[m])
                r = m - 1;
            else {
                l = m;
                break;
            }
        }
        // 因为 l<=r 退出循环后, r 必然位于插入位置
        return l;
    }
};

🌼搜索二维矩阵

74. 搜索二维矩阵 - 力扣(LeetCode)

1)别混淆 mid 和 m,此处 m 是 m 行,mid 才是中间值

2)对第 3 种情况,target == matrix[][],进行处理

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        int l = 0, r = m*n - 1; // 二维转一维
        while (l < r) {
            int mid = (l + r + 1) >> 1;
            if (target > matrix[mid/n][mid%n]) // 一维转二维
                l = mid;
            else if (target < matrix[mid/n][mid%n])
                r = mid - 1;
            else {
                l = mid;
                break;
            }
        }
        return matrix[l/n][l%n] == target;
    }
};

🌼排序数组元素第一和最后一个位置

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

1)利用 while (l <= r) { ... l = m + 1 ... r = m - 1 };  左闭右闭区间

退出循环时,l 的位置就是 >= target 的最小的数

r == l - 1

2)只需求出第一个位置,即可取巧得到最后一个位置,现在有二分函数 lowerbound(nums, target) 得到第一个位置,最后一个位置即 lowerbound(nums, target + 1) - 1

3)奇数个元素,m = (l + r) / 2,取到中间的元素;偶数个元素,因为整数默认下取整,会取中间两个元素左边那个

坑:

1)不要用 >> 1,要用 / 2,不知道力扣是不是不支持位移运算符(>> 1 会超出时间限制) 

2)如果想要从 r = m - 1 开始,那么最后应该 return r;   r 此时位于最后一个位置(详情看代码 2)(用例1模拟一下)

代码 1

class Solution {
public:
    // >= target 的最小的数的位置
    int lowerbound(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while (l <= r) {
            int m = l + (r - l) / 2;
            if (target > nums[m])
                l = m + 1;
            else
                r = m - 1;
        }
        return l; // 第一个位置
    }
    vector<int> searchRange(vector<int>& nums, int target) {
        int start = lowerbound(nums, target);

        if (start >= nums.size() || nums[start] != target)
            return {-1, -1};

        int end = lowerbound(nums, target + 1) - 1;
        return {start, end};
    }
};

代码 2

class Solution {
public:
    // >= target 的最小的数的位置
    int lowerbound(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while (l <= r) {
            int m = l + (r - l) / 2;
            if (target < nums[m])
                r = m - 1;
            else
                l = m + 1;
        }
        return r; // 最后一个位置
    }
    vector<int> searchRange(vector<int>& nums, int target) {
        int end = lowerbound(nums, target);

        if (end < 0 || nums[end] != target)
            return {-1, -1};

        int start = lowerbound(nums, target - 1) + 1;
        return {start, end};
    }
};

🌼旋转排序数组

33. 搜索旋转排序数组 - 力扣(LeetCode)

1)二分时,套 while (l <= r) 的模板,mid 位于中间 OR 中间偏左位置

此时,[l, mid] OR [mid + 1, r],至少一个区间是有序的,所以对左右区间的有序分类讨论

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = nums.size();
        int l = 0, r = n - 1;
        // 二分找到 k 的位置
        while (l <= r) {
            int mid = (l + r) / 2;

            // target 位于 mid
            if (nums[mid] == target)
                return mid;

            // 左边有序
            else if (nums[l] <= nums[mid]) {
                // target 位于左边(不包括 mid)
                if (nums[l] <= target && target < nums[mid]) 
                    r = mid - 1;
                else 
                    l = mid + 1;
            }

            // 右边有序
            else {
                // target 位于右边(不包括 mid)
                if (nums[mid] < target && target <= nums[r])
                    l = mid + 1;
                else
                    r = mid - 1;
            }
        }
        return -1; // 未找到
    }
};

💪旋转排序数组中的最小值

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

上一题是找目标值,本题是找最小值(都满足部分有序)

本题每次旋转,将最后一个值提取到最前面

可以画几个例子多验证一下:2 0 1,1 2 0,3 4 5 2,5 2 3 4

最小值处于断崖的第一个位置,显而易见,肯定位于无序一边

所以每次压缩有序部分,到无序部分找,注意结合例子处理边界

class Solution {
public:
    int findMin(vector<int>& nums) {
        int n = nums.size();
        int l = 0, r = n - 1;
        while (l <= r) { // l < r 也行
            // 单调升序
            if (nums[l] <= nums[r]) // 用 = 防止单个元素时死循环
                return nums[l];

            int m = (l + r) / 2;
            // 左边有序
            if (nums[m] >= nums[l]) // 用 = 防止 r 跳过最小值
                l = m + 1; // 去右边找
            else
                r = m; // 不用 m-1 防止跳过最小值
        }
        return nums[l];
    }
};

💪两个正序数组的中位数

4. 寻找两个正序数组的中位数 - 力扣(LeetCode)

结合这篇博客理解一下,用删除(淘汰)的思路
寻找两个正序数组的中位数(292) | 小浩算法 (geekxh.com)

辅助数组 findKth(nums1, i, nums2, j, k),i, j 是两个数组起始索引,第 k 大元素

如果第一个数组起始位置 i + 2/k - 1 的值 < 第二个数组起始位置 j + 2/k - 1 的值

那么就淘汰掉第一个数组前 2/k 个元素,反之淘汰另一个数组前 2/k 个元素

直到 k == 1,此时比较两个数组起始第 1 个元素大小即可

或者一个数组为空(即 i >= nums1.size() 或 j >= nums2.size())

时间 O(log( max(m, n) ))

class Solution {
public:

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size(), m = nums2.size();
        int left = (n + m + 1) / 2, right = (n + m + 2) / 2; // 中间值索引 left 和 right
        return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
    }

    // nums1 起始索引 i, nums2 起始索引 j, 返回合并数组 第 k 个元素(1开始算)
    int findKth(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
        if (i >= nums1.size()) // nums1 空数组
            return nums2[j + k - 1];
        if (j >= nums2.size()) // nums2 空数组
            return nums1[i + k - 1];
        if (k == 1)
            return min(nums1[i], nums2[j]); // 返回较小值

        // 2/k 位置的值

        // 如果一个数组 k/2 处超出范围, 无法判断中位数是否位于这个数组
        // 但是另一个数组前 k/2 个肯定没有中位数
        // 取 MAX, 淘汰另一个数组前 k/2 个元素
        int mid1 = (i + k/2 - 1 < nums1.size()) ? nums1[i + k/2 - 1] : INT_MAX;
        int mid2 = (j + k/2 - 1 < nums2.size()) ? nums2[j + k/2 - 1] : INT_MAX;

        // 递归二分
        if (mid1 < mid2) // mid1 淘汰 k/2
            return findKth(nums1, i + k/2, nums2, j, k - k/2);
        else // mid2 淘汰 k/2
            return findKth(nums1, i, nums2, j + k/2, k - k/2);
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【个人博客搭建】(22)申请QQ开发者

这里我们要引入的一个概念是OAuth - OAuth 2.0是一个行业标准的授权协议&#xff0c;用于处理用户数据访问和分享的安全问题。它允许用户将他们对某些服务的访问权限授权给第三方应用&#xff0c;而无需分享他们的用户名和密码。以下是对OAuth 2.0的介绍&#xff1a; 基本概念 …

Flutter中同步与异步

一&#xff0c;同步/异步的理解 1&#xff0c;await&#xff1a;同步机制 同步操作会阻止其他操作执行&#xff0c;直到完成为止。同步就好比打电话一样&#xff0c;打电话时都是一个人在说另一个人听&#xff0c;一个人在说的时候另一个人等待&#xff0c;等另一个人说完后再…

Python001

Python 是一种高级编程语言。它具有以下显著特点&#xff1a;1. 简单易学&#xff1a;语法相对简洁明了&#xff0c;对初学者很友好。2. 丰富的库&#xff1a;拥有大量强大的内置库和第三方库&#xff0c;可用于各种领域&#xff0c;如数据分析、机器学习、Web 开发等。3. 可读…

基于STM32开发的智能语音控制系统

目录 引言环境准备智能语音控制系统基础代码实现&#xff1a;实现智能语音控制系统 4.1 语音识别模块数据读取4.2 设备控制4.3 实时数据监控与处理4.4 用户界面与反馈显示应用场景&#xff1a;语音控制的家居设备管理问题解决方案与优化收尾与总结 1. 引言 随着人工智能技术…

C51学习归纳7 --- LED点阵显示静态图片和动画

今天学习一个非常常用的功能。外面的流动字母的LED大屏大家应该很常见吧。今天&#xff01;学完这个&#xff0c;你就可以自己设计一个LED大屏了&#xff01; 一、开发板原理图 首先我们看点阵屏幕的输入信号&#xff0c;有P0_X和DP_X控制。P0_X直接就是芯片的P0输出端口&…

vb开源项目推荐:PhotoDemon9.0一键批量去除图片水印

PhotoDemon 9.0作为一款开源免费的照片编辑器&#xff0c;提供了丰富的图片编辑和处理功能&#xff0c;可以通过PhotoDemon的批处理功能结合一些编辑技巧&#xff0c;来实现批量去除图片水印的目的。 以下是一个可能的步骤指南&#xff0c;用于在PhotoDemon 9.0中通过批处理间…

无人机EasyDSS推拉流视频直播技术在农业植保中的精准应用与展望

随着科技的飞速发展&#xff0c;无人机在农业领域的应用越来越广泛&#xff0c;特别是在农业植保方面&#xff0c;无人机以其独特的优势&#xff0c;为农业生产带来了革命性的改变。 无人机在农业植保中的应用主要体现在两个方面&#xff1a;提高工作效率和精准喷洒药物。在以…

SM201,SM203主控模块备件

SM201,SM203主控模块备件。MACSV软件安装&#xff1b;二、软件组成及各部分功能&#xff1b;三、组态流程&#xff1b;四、组态详解SM201,SM203主控模块备件&#xff08;组态各部分的操作过程及基本原理&#xff09;。一、MACSV系统软件安装软件安装——计算机角色在每台计算机…

Unity 之 代码修改材质球贴图

Unity 之 代码修改材质球贴图 代码修改Shader&#xff1a;ShaderGraph&#xff1a;材质球包含属性 代码修改 meshRenderer.material.SetTexture("_Emission", texture);Shader&#xff1a; ShaderGraph&#xff1a; 材质球包含属性 materials[k].HasProperty("…

LlamaIndex三 配置

前言 在上篇LlamIndex二 RAG应用开发 - 掘金 (juejin.cn)中&#xff0c;我们学习到LlamaIndex对RAG的全面支持。这篇文章&#xff0c;我们就来细化这个过程&#xff0c;尝试各种配置选项&#xff0c;满足不同场景需求。学习过后&#xff0c;大家再开发RAG应用&#xff0c;会更…

Vue11-键盘事件

一、键盘事件&#xff1a;keydown和keyup事件 keydown 和 keyup 是两种常用于处理键盘输入事件的JavaScript事件。当你在网页的输入框或其他可输入元素上按下或释放键盘上的某个键时&#xff0c;这些事件就会被触发。 1-1、keydown 事件 当用户按下键盘上的某个键时&#xff…

matplotlib 动态显示梯度下降过程

文章目录 简介曲线下降曲面下降 简介 梯度下降是一种优化算法&#xff0c;常用于寻找函数的最小值或最大值。它通过迭代更新参数的方式逐步减小&#xff08;或增大&#xff09;目标函数的值&#xff0c;直到达到某个停止条件为止。梯度下降的基本思想是沿着目标函数的负梯度方…

声量2024 | 脱离『生活监狱』——对部分主流价值的质疑与冒犯

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 场地支持 / 阿那亚 联合制作 / 声量The Power of Voice 特别鸣谢 / 深夜谈谈播客网络 本期节目录制于第二届「声量The Power of Voic…

基于 Delphi 的前后端分离:之三,使用 HTMX

# 前请提要 基于 Delphi 的前后端分离&#xff1a;之一_delphi 后台vue-CSDN博客 基于 Delphi 的前后端分离&#xff1a;之二_后端 框架 delphi-CSDN博客 # 发现一个非常好的前端框架 - HTMX 这里仍然使用之二里面提到的页面模板&#xff0c;但采用 HTMX 来和后端交互&#…

项目-基于LangChain的ChatPDF系统

问答系统需求文档 一、项目概述 本项目旨在开发一个能够上传 PDF 文件&#xff0c;并基于 PDF 内容进行问答互动的系统。用户可以上传 PDF 文件&#xff0c;系统将解析 PDF 内容&#xff0c;并允许用户通过对话框进行问答互动&#xff0c;获取有关 PDF 文件内容的信息。 二、…

python中的函数递归

函数递归&#xff0c;就是一个函数&#xff0c;自己调用自己。 如上图所示&#xff0c;是一段通过定义函数&#xff0c;编写函数体来实现for循环。实现的是从1到n的累乘。即求n的阶乘&#xff0c; 如上图所示&#xff0c;是一段函数的递归来实现1到n的累乘操作&#xff0c;将1*…

思维,CF1575K - Knitting Batik

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1575K - Knitting Batik 二、解题报告 1、思路分析 诈骗题&#xff0c;上面…

变声器软件免费版有哪些?国内外12大热门变声器大盘点!(新)

变声软件是一种人工智能AI音频处理工具&#xff0c;允许用户实时修改自己的声音或改变预先录制的音频。这些软件解决方案可提供不同的效果&#xff0c;如改变声音的音调或速度&#xff0c;或将我们的声音转换成其他人或其他东西的声音&#xff0c;如名人、卡通人物、机器人或不…

C++开源项目:pathcopycopyV20源码及运行程序

PathCopyCopy 是一个开源的 Windows 资源管理器扩展项目&#xff0c;旨在为用户提供一个更加高效、便捷的文件路径复制和管理工具。以下是关于 PathCopyCopy 开源项目的详细介绍&#xff1a; 1. 项目概述 2. 项目技术分析 3. 项目功能 4. 项目特点 5. 项目应用场景 6. 项目…

记一次源码部分丢失后补救过程

起因 最近植物大战僵尸杂交版玩的入迷&#xff0c;写了一个“神奇”小工具&#xff0c;来辅助游戏。用Git新建一个库&#xff0c;想把代码备份到GitHub&#xff0c;结果push错库了&#xff0c;无奈reset&#xff0c;结果把本地项目一起reset了&#xff0c;结果就是源代码丢失。…