【算法练习Day1】二分查找移除元素

news2024/9/25 21:26:55

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 二分查找
    • 解决方法一:左闭右开[left<=right),right = nums.size() - 1;
    • 解决方法二:左闭右闭(left<right),right = nums.size();
  • 移除元素
    • 暴力求解
    • 双指针遍历
    • 关于移除元素
  • 总结:

二分查找

704.二分查找

● 什么是区间不变量? 比如 区间取左闭右闭的话 那么每次区间二分 范围都是新区间的左闭右闭 后面做判断时 要一直基于这个左闭右闭的区间,其实区间定义成开或者闭都没有什么关系 只是要明确每次收缩范围后 范围内的元素是哪些 注意会不会漏掉边界

● 需要注意二分的几种情况
○ 当l = 0, r = n的时候因为r这个值我们在数组中无法取到,while(l < r) 是正确写法
○ 当l = 0, r = n - 1的时候因为r这个值我们在数组中可以取到,while(l <= r) 是正确写法
主要看能不能取到这个值

● 主要是对左闭右开[left<=right),左闭右闭(left<right)区别和怎么更新left,right的值有一定误解

由于数组元素为有序排列,我们仅需要确定搜索的左右边界。在该题中存在两种情况,即右边界的选择:

解决方法一:左闭右开[left<=right),right = nums.size() - 1;

在这种情况下,每次的搜索区间为 [left, right] 即左闭右闭区间,此时对应的循环条件应为 while (left <= right),终止条件为 left == right + 1,即 [right + 1, right],此时区间为空,故循环终止,程序返回 -1 即可;

class Solution {
public://这种情况是前闭后闭的情况
    int search(vector<int>& nums, int target) {
        int left=0;int right=nums.size()-1;
        while(left<=right)
        {
            int mid=(left+right)/2;
            if(nums[mid]<target)left=mid+1;
            else if(nums[mid]>target)right=mid-1;
            else return mid;
        }
        return -1;
    }
};

由于mid被判断不是目的值,故两边界取的是mid的前一个值(改变右边界时)或mid的后一个值(改变左边界时),这样写的好处是把已经确定不在判断范围内的值给去掉,所以才写成从mid的前一个数或后一个数判断,而判断区间里由于两边区域都是闭区间所以可以带等于号。

易错:注意mid要放在while里面,mid本身是一直变化的

解决方法二:左闭右闭(left<right),right = nums.size();

对于这种情况,由于数组,此时的搜索区间为[left, right)即左闭右开区间,此时对应的循环条件为 while (left < right),终止条件为 left == right,即 [right, right],此时区间内仅存一个元素 right,直接返回 -1 是不对的,还需对该索引进行判断。

class Solution {
public://这种情况是前闭后开的情况
    int search(vector<int>& nums, int target) {
        int left=0;int right=nums.size();
        while(left<right)
        {
            int mid=(left+right)/2;
            if(nums[mid]<target)left=mid+1;
            else if(nums[mid]>target)right=mid;
            else return mid;
        }
        return -1;
    }
};

第二种方法是左闭右开的情况,由于两侧边界不能相等,故判断区域不带等于号,右开:虽然右边界更改时,也不取mid值,但是由于右边区间是开区间,所以写成right=mid;是可行的,等于mid但是取不到

● 二分的最大优势是在于其时间复杂度是O(logn),因此看到有序数组都要第一时间反问自己是否可以使用二分。

● 其实二分还有很多应用场景,有着许多变体,比如说查找第一个大于target的元素或者第一个满足条件的元素,都是一样的,根据是否满足题目的条件来缩小答案所在的区间,这个就是二分的本质。

注意:二分的使用前提:有序数组

● 关于二分mid溢出问题:

  • mid = (l + r) / 2时,如果l + r 大于 INT_MAX(C++内,就是int整型的上限),那么就会产生溢出问题(int类型无法表示该数)

  • 所以写成 mid = l + (r - l) / 2或者 mid = l + ((r - l) >> 1) 可以避免溢出问题

● 对于二进制的正数来说,右移x位相当于除以2的x几次方,所以右移一位等于➗2,用位运算的好处是比直接相除的操作快

移除元素

27.移除元素

这道题主要是考察选手对于数组方面的掌握,

分两种方法 :一种是常见的暴力求解O(N*2),另一种则是稍微有些巧妙的双指针遍历O(N)

暴力求解

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size=nums.size();
        for(int i=0;i<size;i++)
        {
            if(nums[i]==val)
            {
                for(int j=i+1;j<size;j++)
                nums[j-1]=nums[j];//避免溢出的处理方法
                size--;
                i--;
            }
        }
        return size;
    }
};

暴力求解主要是要注意size来记录返回数组的个数,每次找到val值后,i - -,这是因为找到val后val后的每个值都会向前一位,来挤掉之前的val值,让i - -,是从当前发现的val的下一个值来开始遍历,以免有落下的数没有判断。

双指针遍历

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int fast=0,slow=0;
        for(;fast<nums.size();fast++)
        if(nums[fast]!=val)
        nums[slow++]=nums[fast];
        return slow;
    }
};

slow、fast一开始都指向原点,然后fast向后走,直到找到val,开始做替换并且slow开始指向下一个位置,当fast走到最后,就说明所有的元素都被遍历完了,此时的slow值,就代表数组元素个数。

关于移除元素

● 快指针可以理解成在旧数组中找非目标元素,然后赋值给慢指针指向的新数组,虽然都指向一个数组

● 关于二分法和移除元素的共性思考
都是在不断缩小 left 和 right 之间的距离,每次需要判断的都是 left 和 right 之间的数是否满足特定条件。对于「移除元素」还可以理解为,拿 right 的元素也就是右边的元素,去填补 left 元素也就是左边的元素的坑,坑就是 left 从左到右遍历过程中遇到的需要删除的数,因为题目最后说超过数组长度的右边的数可以不用理,所以是以 left 为主,这样可能更直观一点。

● fast < nums.size() 和 fast <= nums.size()-1 没什么区别,那为什么第二个会在空数组时报数组越界的错误?
因为vector的size()函数返回值是无符号整数,空数组时返回了0,再减个1会溢出

总结:

今天的两道题其实在很久之前做过,但当时没有真正理解里面的细节问题,现在总算理解了。接下来,我们继续进行算法练习·。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

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

相关文章

【pytest】 pytest拓展功能 pycharm PermissionError: [Errno 13] Permission denied:

目录 1. pytest-html 1.1 PermissionError: [Errno 13] Permission denied: D:\\software\\python3\\anconda3\\Lib\\site-packages\\pytest_html\\__pycache__\\tmp_ttoasov 1.2错误原因 2. 失败用例重试 3. 用例并行执行 pytest-parallel 1. pytest-html 管理员打开 A…

Java入门级基础教学(史上最详细的整合)

目录 一&#xff1a;基础语法 1.“Hello word” 2.Java的运行机制 3. Java基本语法 1.注释、标识符、关键字 2.数据类型&#xff08;四类八种&#xff09; 4.类型转换 1.自动转换 2.强制转换 5.常量和变量 1.常量 2.变量 3.变量的作用域 6.运算符 1.算数运算符 …

从零开始搭建成绩查询系统

在当前的数字化时代&#xff0c;教育行业借助技术手段不断推动教学效果的提升。作为教师&#xff0c;搭建一个专属的成绩查询系统可以更好地管理学生成绩&#xff0c;并即时向家长反馈。本文将详细介绍如何从零开始搭建一个成绩查询系统&#xff0c;以提升教学管理的便捷性和效…

Qt(day4)

思维导图 QT连接TCP网络通信 服务器 ser.h #ifndef SER_H #define SER_H#include <QWidget> #include<QTcpServer> //服务器头文件 #include<QTcpSocket> //客户端头文件 #include<QMessageBox> //消息对话框 #include<QList> …

已解决 ValueError: Found array with dim 3. Estimator expected <= 2.

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

“新”心相印 | 长沙市网络代表人士培训班“破冰”联谊“湘”味十足

搜狐网湖南&#xff08;文/莫谦&#xff09;9月18日至9月22日&#xff0c;首期长沙市网络代表人士专题培训班在北京大学举行&#xff0c;培训班学员主要是长沙网络名人联盟成员&#xff0c;涵盖抖音达人、微博博主、网络作家、网络大V等。 为了加强长沙网络名人联盟组织建设&a…

exec函数族

1.execl函数 #include <unistd.h> int execl(const char *path, const char *arg, ...); 参数&#xff1a; -path:需要指定的执行文件的路径或者名称 -*arg:是可执行文件所需要的参数列表 第一个参数一般没有什么作用&#xff0c;一般写的是执行的程序的名称 从第二个参…

鉴源实验室 | 系统逻辑漏洞挖掘实践

作者 | 林海文 上海控安可信软件创新研究院汽车网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 前 言 当谈及安全测试时&#xff0c;逻辑漏洞挖掘一直是一个备受关注的话题&#xff0c;它与传统的安全漏洞&#xff08;如…

SSM整合(细节拉满)|将Mybatis、Spring、SpringMVC三个框架整合起来,通过一个demo来练习

环境要求 环境: IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 要求: 需要熟练掌握MySQL数据库&#xff0c;Spring&#xff0c;JavaWeb及MyBatis知识&#xff0c;简单的前端知识; 数据库环境 创建一个存放书籍数据的数据库表&#xff0c;并插入一些示例数据 SSM整合 新建一个空的M…

网安须知|什么是护网行动?什么是红蓝对抗?

01 什么是护网行动 护网行动是以公安部牵头的&#xff0c;用以评估企事业单位的网络安全的活动。 具体实践中&#xff0c;公安部会组织攻防两方&#xff0c;进攻方会在一个月内对防守方发动网络攻击&#xff0c;检测出防守方&#xff08;企事业单位&#xff09;存在的安全漏洞…

深入学习 Redis - 分布式锁底层实现原理,以及实际应用

目录 一、Redis 分布式锁 1.1、什么是分布式锁 1.2、分布式锁的基础实现 1.2.1、引入场景 1.2.2、基础实现思想 1.2.3、引入 setnx 1.3、引入过期时间 1.4、引入校验 id 1.5、引入 lua 脚本 1.5.1、引入 lua 脚本的原因 1.5.2、lua 脚本介绍 1.6、过期时间续约问题&…

OpenMMLab MMYOLO目标检测应用示例与常见问题(三)

基于MMYOLO的电离图实时目标检测基准 数据集 数字电离图是获取实时电离层信息的最重要方式。电离层结构检测对于准确提取电离层关键参数具有重要的研究意义。 本研究利用中国科学院在海南、武汉和怀来获得的4311张不同季节的电离图建立数据集。使用labelme手动注释包括 Laye…

实现高并发内存池(C++)

什么是内存池 池化技术 所谓“池化技术”&#xff0c;就是程序先向系统申请过量的资源&#xff0c;然后自己管理以备不时之需。之所以要申请过量的资源&#xff0c;是因为每次申请该资源都有较大的开销&#xff0c;不如提前申请好&#xff0c;这样使用时就会变得非常快捷&…

2023年华数杯数学建模C题母亲身心健康对婴儿成长的影响解题全过程文档及程序

2023年华数杯全国大学生数学建模 C题 母亲身心健康对婴儿成长的影响 原题再现&#xff1a; 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c;还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、…

同为科技(TOWE)专业防雷滤波桌面PDU超级插座

2023年第19届杭州亚运会开幕在即&#xff0c;相较于以往&#xff0c;本届杭州亚运会的一大看点就是电竞项目将首次以正式比赛项目的身份亮相亚运赛场&#xff0c;让更多受众能够领略电竞的魅力。当前社会&#xff0c;电竞作为一种新兴的娱乐、社交方式&#xff0c;让很多年轻人…

Feign实战-Springboot集成OpenFeign Demo以及参数详解

最近整理一下微服务的文章&#xff0c;先拿一直用的OpenFeign开刀 思考&#xff1a;微服务之间如何方便优雅的实现服务间的远程调用 一、说说openFeign是什么吧&#xff1f; 说到这个&#xff0c;那不得不先说说RPC 1.什么是RPC RPC 全称是 Remote Procedure Call &#x…

程序员还在为兼职接单发愁,快看看这几个宝藏平台吧!!!

在当今经济发展压力巨大的背景下&#xff0c;总有人还在与生活顽强对抗&#xff0c;拿什么和生活对抗嘞&#xff0c;那当然只有马内咯&#xff0c;尤其是对于程序员而言&#xff0c;现在内卷严重&#xff0c;如果能做一点线上兼职搞点马内&#xff0c;那岂不美哉&#xff0c;如…

计算机毕业设计 基于SpringBoot餐厅点餐系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

Android ANR问题触发机制

1 Anr类型 ​ Anr一般有四种类型。 1.1 input dispatching timeout ​ 主要时按键或触摸屏事件在5s内没有响应。这个时间在ActivityManagerService中定义。 C:\Users\wangjie\AppData\Local\Android\Sdk\sources\android-32\com\android\server\am\ActivityManagerService.…

嵌入式学习 - 用电控制电

目录 前言&#xff1a; 1、继电器 2、二极管 3、三极管 3.1 特殊的三极管-mos管 3.2 npn类型三极管 3.3 pnp类型三极管 3.4 三极管的放大特性 3.5 mos管和三极管的区别 前言&#xff1a; 计算机的工作的核心原理&#xff1a;用电去控制电。 所有的电子元件都有数据手册…