hot100 -- 二分查找

news2024/11/29 14:53:02

目录

前言

🎂搜索插入位置

🌼搜索二维矩阵

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

🌼旋转排序数组

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

💪两个正序数组的中位数


前言

二分算法学习_时间超限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);
    }
};

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

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

相关文章

Vue10-事件修饰符

一、示例&#xff1a;<a>标签不执行默认的跳转行为 1-1、方式一 <a href"http://www.baidu.com" onclick"event.preventDefault();">点击我</a> 1-2、方式二 1-3、方式三&#xff1a;事件修饰符 二、Vue的六种事件修饰符 2-1、prevent&…

Edge怎么关闭快捷键

Edge怎么关闭快捷键 在Edge浏览器中&#xff0c;你可以通过以下步骤关闭快捷键&#xff1a; 打开Edge浏览器&#xff0c;输入&#xff1a;edge://flags 并按下回车键。 在Flags页面中&#xff0c;搜索“快捷键”(Keyboard shortcuts)选项。 将“快捷键”选项的状态设置为“…

注册小程序

每个小程序都需要在 app.js 中调用 App 方法注册小程序实例&#xff0c;绑定生命周期回调函数、错误监听和页面不存在监听函数等。 详细的参数含义和使用请参考 App 参考文档 。 整个小程序只有一个 App 实例&#xff0c;是全部页面共享的。开发者可以通过 getApp 方法获取到全…

HuggingFace团队亲授大模型量化基础: Quantization Fundamentals with Hugging Face

Quantization Fundamentals with Hugging Face 本文是学习https://www.deeplearning.ai/short-courses/quantization-fundamentals-with-hugging-face/ 这门课的学习笔记。 What you’ll learn in this course Generative AI models, like large language models, often exce…

转让无区域商业管理公司挺批行业包变更

无区域的名称我们可以直接进行名称的申请核准。 从新规施行之后&#xff0c;国家局核名批准难度更高。新申请的无区域名称已经停批了&#xff0c;进行核名将更难&#xff0c;而需要满足一定条件并在成立一年后才能变更升级名称。而这个过程并非易事&#xff0c;难度非常高。可以…

45-1 waf绕过 - 文件上传绕过WAF方法

环境准备: 43-5 waf绕过 - 安全狗简介及安装-CSDN博客然后安装dvwa靶场:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客打开dvwa靶场,先将靶场的安全等级调低,然后切换到文件上传 一、符号变异 在PHP中,由于其弱类型特性,有时候仅有一…

JavaSE——抽象类和接口

目录 一 .抽象类 1.抽象类概念 2.抽象类语法 3.抽象类特性 4.抽象类的作用 二. 接口 1.接口的概念 2.语法规则 3.接口的使用 4.接口特性 5.实现多个接口 6.接口间的继承 三.抽象类和接口的区别 一 .抽象类 1.抽象类概念 在面向对象的概念中&#xff0c;所有的对…

SpringCloud整合OpenFeign实现微服务间的通信

1. 前言 1.1 为什么要使用OpenFeign&#xff1f; 虽说RestTemplate 对HTTP封装后, 已经⽐直接使⽤HTTPClient简单⽅便很多, 但是还存在⼀些问题. 需要拼接URL, 灵活性⾼, 但是封装臃肿, URL复杂时, 容易出错. 代码可读性差, ⻛格不统⼀。 1.2 介绍一下微服务之间的通信方式 微…

Zabbix实现邮件和钉钉实时告警(使用python脚本)

告警和通知 告警是监控的主要职能,是指将到达某一阈值事件的消息发送给用户,让用户在事件发生的时候即刻知道监控项处于不正常状态,从而让用户来决定是否采取相关措施。 zabbix中,告警是由一系列的流程组成的,⾸首先是触发器到达阈值,接下是Active对事件信息进行处理,其…

TCP/IP协议分析实验:通过一次下载任务抓包分析

TCP/IP协议分析 一、实验简介 本实验主要讲解TCP/IP协议的应用&#xff0c;通过一次下载任务&#xff0c;抓取TCP/IP数据报文&#xff0c;对TCP连接和断开的过程进行分析&#xff0c;查看TCP“三次握手”和“四次挥手”的数据报文&#xff0c;并对其进行简单的分析。 二、实…

ElasticSearch学习笔记之一:介绍及EFK部署

1. 系统概述 The Elastic Stack&#xff0c;包括Elasticsearch、Kibana、Beats和Logstash&#xff08;也成为ELK Stack&#xff09; Elasticsearch&#xff1a;简称ES&#xff0c;是一个开源的高扩展的分布式全文搜索引擎&#xff0c;是整个Elastic Stack技术栈的核心。它可以…

【MySQL】聊聊MySQL常见的SQL语句阻塞场景

在平时的业务中&#xff0c;可能一个简单的SQL语句也执行很慢&#xff0c;这种情况其实大多数都是要么没有使用索引&#xff0c;要么出现锁竞争造成执行阻塞。本篇主要来介绍具体的场景 CREATE TABLE t ( id int(11) NOT NULL, c int(11) DEFAULT NULL, PRIMARY KEY (id) ) ENG…

用HAL库改写江科大的stm32入门-6-4 PWM驱动舵机

接线图&#xff1a; 如何控制一个舵机 舵机的控制由一个脉冲宽度调制信号(PWM波&#xff09;来实现&#xff0c;该信号在这个实验里使用stm32来发出。 舵机通讯协议&#xff1a; 对应设置参数&#xff1a; ARR的值为19999 CCR的值为500~2500(生成占空比是2.5%~12.5%的波形)…

[经验] 昆山教育网(昆山教育网中小学报名) #媒体#职场发展#微信

昆山教育网&#xff08;昆山教育网中小学报名&#xff09; 昆山教育局网站 网站&#xff1a;昆山市教育局 昆山市教育局全面贯彻执行党和国家的教育方针、政策&#xff0c;落实有关教育工作的法律、法规&#xff1b;负责制定本市教育工作的实施意见和措施&#xff0c;并监督…

Java基础_异常

Java基础_异常 异常体系介绍编译时异常和运行时异常异常的作用异常的处理方式JVM默认的处理方式自己处理&#xff08;捕获异常&#xff09;try...catch灵魂四问Throwable的成员方法 抛出处理 综合练习自定义异常来源Gitee地址 异常体系介绍 异常是什么&#xff1f; 程序中可能出…

LabVIEW2017破解安装教程

LabVIEW2017破解安装教程&#xff1a; 1、新版LabVIEW2017分为32位和64位两个平台&#xff0c;多种语言版本(需要LabVIEW2017中文版的朋友请选择WinChn版本)&#xff0c;大家选择自行选择符合系统的版本下载并解压 2、本次安装以Win 7 64位系统为例&#xff0c;运行“2017LV-64…

【Vscode配置java环境并配置stringboot】

1.VSCODE配置JAVA环境 参考这篇文章配置JAVA环境&#xff1a;连接 java版本&#xff0c;我是win11系统,我下载的JAVA安装版本是下面&#xff0c;是最新版的&#xff1a; 配置环境&#xff1a;步骤很简单&#xff0c;就是向系统环境变量中添加路径&#xff0c;参考上面文章中的…

AddressSanitizer理论及实践:heap-use-after-free、free on not malloc()-ed address

AddressSanity&#xff1a;A Fast Address Sanity Checker 摘要 对于C和C 等编程语言&#xff0c;包括缓冲区溢出和堆内存的释放后重用等内存访问错误仍然是一个严重的问题。存在许多内存错误检测器&#xff0c;但大多数检测器要么运行缓慢&#xff0c;要么检测到的错误类型有…

【Java】解决Java报错:IllegalArgumentException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 非法的参数值2.2 空值或 null 参数2.3 非法的数组索引 3. 解决方案3.1 参数验证3.2 使用自定义异常3.3 使用Java标准库中的 Objects 类 4. 预防措施4.1 编写防御性代码4.2 使用注解和检查工具4.3 单元测试 结语 引言 在Java编程…

C++笔记之一个函数多个返回值的方法、STL::pair、STL::tuple、STL::tie的用法

C++笔记之一个函数多个返回值的方法、STL::pair、STL::tuple、STL::tie的用法 —— 2024-06-08 杭州 code review! 文章目录 C++笔记之一个函数多个返回值的方法、STL::pair、STL::tuple、STL::tie的用法一.从一个函数中获取多个返回值的方法1. 使用结构体或类2. 使用`std::t…