代码随想录训练营Day1:二分查找与移除元素

本专栏内容为:代码随想录训练营学习专栏,用于记录训练营的学习经验分享与总结。

文档讲解:代码随想录
视频讲解:二分查找与移除元素

💓博主csdn个人主页:小小unicorn
⏩专栏分类:C++
🚚代码仓库:小小unicorn的代码仓库🚚
🌹🌹🌹关注我带你学习编程知识

Day1

  • 二分查找
    • 题目分析
    • 解题思路:
      • 写法一:
      • 写法二:
  • 移除元素
    • 题目分析:
    • 思路:
      • 暴力:
      • 双指针法:
  • 总结:

二分查找

题目分析

题目描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

题目来源:704.二分查找
在这里插入图片描述

解题思路:

这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。

二分查找涉及的很多的边界条件,逻辑比较简单,但就是写不好。例如到底是 while(left < right) 还是 while(left <= right),到底是right = middle呢,还是要right = middle - 1呢?

大家写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。

写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

写法一:

第一种写法,我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] 。

在这个区间内要有以下两点:

1.while (left <= right)
要使用 <= 。
这是因为left == right是有意义的,所以使用 <=。

2.if (nums[middle] > target)
那么 right 要赋值为 middle - 1。
这是因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
例如在数组:1,2,3,4,7,9,10中查找元素2,如图所示:
在这里插入图片描述

代码解决:

class Solution 
{
public:int search(vector<int>& nums, int target) {//定义左闭右闭区间int left=0;int right=nums.size()-1;while(left<=right){int middle=left+((right-left)/2);//说明target在左区间if(nums[middle]>target)right=middle-1;//target在右区间else if(nums[middle]<target)left=middle+1;else//找到了return middle;}//未找到目标值return -1;}
};

时间复杂度:O(log n)
空间复杂度:O(1)

写法二:

如果说定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。

有如下两点:

1.while (left < right)
这里使用 <
这是因为left == right在区间[left, right)是没有意义的

2.if (nums[middle] > target)
right 更新为 middle
这是因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
在数组:1,2,3,4,7,9,10中查找元素2,如图所示:(注意和方法一的区别)
在这里插入图片描述
代码解决:

class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <int middle = left + ((right - left) >> 1);if (nums[middle] > target) {right = middle; // target 在左区间,在[left, middle)中} else if (nums[middle] < target) {left = middle + 1; // target 在右区间,在[middle + 1, right)中} else { // nums[middle] == targetreturn middle; // 数组中找到目标值,直接返回下标}}// 未找到目标值return -1;}
};

移除元素

题目分析:

题目描述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
题目来源:27.移除元素
在这里插入图片描述

思路:

暴力:

两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。

// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
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];}i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位size--; // 此时数组的大小-1}}return size;}
};

时间复杂度:O(n^2)
空间复杂度:O(1)

双指针法:

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针

快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
在这里插入图片描述

代码解决

class Solution 
{
public:int removeElement(vector<int>& nums, int val) {int slowIndex=0;for(int fastIndex=0;fastIndex<nums.size();fastIndex++){//只要不等于val就往后移动if(val!=nums[fastIndex])nums[slowIndex++]=nums[fastIndex];}return slowIndex;}
};

时间复杂度:O(n)
空间复杂度:O(1)

总结:

在今天,我们通过两道典型例题,知道了什么是二分法,用到了双指针算法思想,希望通过这两道例题,能对双指针和二分法有更深层的理解。

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

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

相关文章

Java进阶(JVM调优)——阿里云的Arthas的使用 安装和使用 死锁查找案例,重新加载案例,慢调用分析

前言 JVM作为Java进阶的知识&#xff0c;是需要Java程序员不断深度和理解的。 本篇博客介绍JVM调优的工具阿里云的Arthas的使用&#xff0c;安装和使用&#xff0c;命令的使用案例&#xff1b;死锁查询的案例&#xff1b;重新加载一个类信息的案例&#xff1b;调用慢的分析案…

通配符匹配

题目链接 通配符匹配 题目描述 注意点 s 仅由小写英文字母组成p 仅由小写英文字母、‘?’ 或 ‘*’ 组成‘?’ 可以匹配任何单个字符‘*’ 可以匹配任意字符序列&#xff08;包括空字符序列&#xff09; 解答思路 最初想到的是dfs 剪枝&#xff0c;但是用例超时了参照题…

STM32笔记—EXTI外部中断

一、简介 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行&#xff1b; 中断优先级&…

maven中的install 和 clean命令,以及compile、、package、test等操作介绍

maven中的install命令 主要就是谁要被其他模块依赖就install谁 Maven工具可以进行clean、compile、install、package、test等操作&#xff0c;但是这些操作有什么用呢&#xff0c;以下面的p2p-exterface为例说明一下&#xff0c;pwp-exterface工程目录如下&#xff1a; com…

centos中安装的goland配置sdk报错:所选的目录不是Go SDK的有效主路经

选中目录后一直报错&#xff1a; 正确的位置&#xff1a; 原因竟然是使用 解压go1.21.4.linux-amd64.tar.gz 包出来&#xff0c;少了scr和test目录&#xff0c;重新解压后可以正确设定SDK主目录。 有同样问题的可以确认一下。 tar -C /usr/local -zxvf go1.19.2.linux-amd64.…

随机链表的复制

题目描述 给你一个长度为n的链表&#xff0c;每个节点包含一个额外增加的随机指针random&#xff0c;该指针可以指向链表中的任何节点或空节点。构造这个链表的深拷贝。 深拷贝应该正好由n个全新节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新节点的nex…

SpringBoot使用Mybatis

SpringBoot使用Mybatis Orm 框架的本质是简化编程中操作数据库的编码&#xff0c;发展到现在基本上就剩两家了&#xff0c;一个是宣称可以不用写一句 Sql 的 Hibernate&#xff0c;一个是可以灵活调试动态 Sql 的 Mybatis ,两者各有特点&#xff0c;在企业级系统开发中可以根…

解决EnableKeyword(“_Emission“)运行状态不起作用

我使用的是Standard Shader&#xff0c;一开始“_Emission”没有开启 当我运行下面的代码&#xff0c;可以看到Inspector窗口已经生效&#xff0c;然而物体本身并没有重新开始渲染&#xff0c;反射没有开启 public GameObject go; // Start is called before the first frame…

极智开发 | CUDA线程模型与全局索引计算方式

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 CUDA线程全局索引计算方式。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq CUDA 线程全局索引的计算,是很容…

nuxt项目相关学习

传统服务端渲染流程 单页面应用 1. nuxt 是什么 Nuxt.js 是一个基于 Vue.js 的通用应用框架。 通过对客户端/服务端基础架构的抽象组织&#xff0c;Nuxt.js 主要关注的是应用的 UI 渲染。 就使用而言,组件写法基本和vue相差不大,区别在于几个钩子函数,以及一些服务端渲染相关…

【Linux】:初识git || centos下安装git || 创建本地仓库 || 配置本地仓库 || 认识工作区/暂存区(索引)以及版本库

&#x1f4ee;1.初识git Git 原理与使用 课程⽬标 • 技术⽬标:掌握Git企业级应⽤&#xff0c;深刻理解Git操作过程与操作原理&#xff0c;理解⼯作区&#xff0c;暂存区&#xff0c;版本库的含义 • 技术⽬标:掌握Git版本管理&#xff0c;⾃由进⾏版本回退、撤销、修改等Git操…

【Excel】如何画不同时序交叉的百分比堆积柱状图

这里写自定义目录标题 1 将两表交叉合并为一个表1.1 步骤一&#xff1a;在两独立表的工作天数和工资列下面按1-n顺次标号。1.2 步骤二&#xff1a;选中两表需要合并的部分&#xff0c;调出自定义排序1.3 步骤三&#xff1a;选项 ——> 按行排序 &#xff08;选完后点确定&am…

Java10新增特性

特性列表 Java 10是Java的一个主要版本更新&#xff0c;引入了许多新功能和改进。以下是一些Java 10的新增特性&#xff1a; 局部变量类型推断&#xff1a;Java 10引入了局部变量类型推断&#xff0c;允许开发者使用关键字"var"来声明局部变量&#xff0c;而无需指定…

【STM32】定时器

systick定时器&#xff1a; 【STM32】Systick定时器-CSDN博客 0.通用定时器框图 1.时钟源 2.控制器 3.输入捕获 计数器实际上是与比较寄存器的影子寄存器进行比较的。 4.输出比较 1.STM32的定时器学习要点 参考手册 STM32F1xx中文参考手册.pdf 林何/STM32F103C8 - 码云 -…

Spring的循环依赖问题

文章目录 1.什么是循环依赖2.代码演示3.分析问题4.问题解决5.Spring循环依赖6. 疑问点6.1 为什么需要三级缓存6.2 没有三级缓存能解决吗&#xff1f;6.3 三级缓存分别什么作用 1.什么是循环依赖 上图是循环依赖的三种情况&#xff0c;虽然方式有点不一样&#xff0c;但是循环依…

合成数据在金融服务中的应用

人工智能在金融服务中有着广泛的应用&#xff0c;从流程自动化到聊天机器人和欺诈检测。据估计&#xff0c;到 447 年&#xff0c;银行从人工智能应用中节省的潜在成本总额将达到 2023 亿美元。 但是&#xff0c;其中一些应用程序有其局限性&#xff0c;因为财务数据是最敏感和…

排序算法的空间复杂度和时间复杂度

一、排序算法的时间复杂度和空间复杂度 排序算法 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性 冒泡排序 O(n) O(n) O(n) O(1) 稳定 直接选择排序 O(n) O(n) O(n) O(1) 不稳定 直接插入排序 O(n) O(n) O(n) O(1) 稳定 快速排序 O(n…

nacos做服务配置和服务器发现

一、创建项目 1、创建一个spring-boot的项目 2、创建三个模块file、system、gateway模块 3、file和system分别配置启动信息,并且创建一个简单的控制器 server.port9000 spring.application.namefile server.servlet.context-path/file4、在根目录下引入依赖 <properties&g…

docker部署es+kibana

es 暴露的端口特别多 &#xff0c;十分耗内存&#xff0c;数据一般要放置到安全目录&#xff0c;挂载 官网推荐的命令&#xff1a;docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" elasticsearch…

高能数造电池3D打印智能制造小试线,开启全固态电池数字化新时代

在科技创新的浪潮中&#xff0c;电池制造领域又迎来了一次突破性的进展。近日&#xff0c;高能数造(西安)技术有限公司重磅推出了其最新电池数字制造装备——全固态电池3D打印智能制造小试线 &#xff0c;这一创新性的技术开启了全固态电池的数字化智造新时代&#xff0c;为全固…