代码随想录训练营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] == target
                return 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.mfbz.cn/a/123217.html

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

相关文章

某卢小说网站登录密码逆向

js逆向&#xff0c;今晚找了一个小说网站&#xff0c;分析一下登录密码的解密逆向过程&#xff0c;过程不是很难&#xff0c;分享下 学习网站aHR0cHM6Ly91LmZhbG9vLmNvbS9yZWdpc3QvbG9naW4uYXNweA 这个就是加密后的密码&#xff0c;今晚就逆向它&#xff0c;其他参数暂时不研究…

python+pytorch人脸表情识别

概述 基于深度学习的人脸表情识别&#xff0c;数据集采用公开数据集fer2013&#xff0c;可直接运行&#xff0c;效果良好&#xff0c;可根据需求修改训练代码&#xff0c;自己训练模型。 详细 一、概述 本项目以PyTorch为框架&#xff0c;搭建卷积神经网络模型&#xff0c;训…

【中间件篇-Redis缓存数据库02】Redis高级特性和应用(慢查询、Pipeline、事务、Lua)

Redis高级特性和应用(慢查询、Pipeline、事务、Lua) Redis的慢查询 许多存储系统&#xff08;例如 MySQL)提供慢查询日志帮助开发和运维人员定位系统存在的慢操作。所谓慢查询日志就是系统在命令执行前后计算每条命令的执行时间&#xff0c;当超过预设阀值,就将这条命令的相关…

腾讯云双11优惠活动有哪些?详细攻略来了!

2023年腾讯云双11大促活动正在火热进行中&#xff0c;百款热门云产品11.11云上盛惠&#xff0c;领折上折代金券最高再省9999元&#xff0c;助力开发者轻松上云&#xff01; 一、腾讯云双11活动入口 活动地址&#xff1a;点此直达 二、腾讯云双11活动时间 即日起至2023-11-30…

基于SSM的电动车上牌管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

2012年计网408

第33题 在 TCP/IP 体系结构中, 直接为 ICMP 提供服务的协议是()A. PPPB. IPC. UDPD. TCP 本题考察TCP/IP体系结构中直接为ICMP协议提供服务的协议。如图所示。这是TCP/IP的四层体系结构。网际层的IP协议是整个体系结构中的核心协议&#xff0c;用于网络互联。网际控制报文协议…

MongoDB副本集特点验证

MongoDB副本集特点验证 mogodb副本集概述副本集搭建副本集结构验证结果源码地址 mogodb副本集概述 MongoDB副本集是将数据同步在多个服务器的过程。 复制提供了数据的冗余备份&#xff0c;并在多个服务器上存储数据副本&#xff0c;提高了数据的可用性&#xff0c; 并可以保证…

To create the 45th Olympic logo by using CSS

You are required to create the 45th Olympic logo by using CSS. The logo is composed of five rings and three rectangles with rounded corners. The HTML code has been given. It is not allowed to add, edit, or delete any HTML elements. 私信完整源码 <!DOCT…

MFC-TCP网络编程服务端-Socket

目录 1、通过Socket建立服务端&#xff1a; 2、UI设计&#xff1a; 3、代码的实现&#xff1a; &#xff08;1&#xff09;、CListenSocket类 &#xff08;2&#xff09;、CConnectSocket类 &#xff08;3&#xff09;、CTcpServerDlg类 1、通过Socket建立服务端&#xff…

分享一本让你真正理解深度学习的书

关注微信公众号&#xff1a;人工智能大讲堂&#xff0c;后台回复udl获取pdf文档。 今天要分享的书是Understanding Deep Learning&#xff0c;作者是西蒙普林斯&#xff0c;英国巴斯大学的荣誉教授&#xff0c;其个人学术能力相当强大&#xff0c;在AI领域有着深厚的学术造诣。…

网络唤醒(Wake-on-LAN, WOL)

远程唤醒最简单的方法&#xff1a;DDNSTOOpenwrt网络唤醒&#xff0c;完美实现。 原帖-远程唤醒_超详细windows设置远程唤醒wol远程连接&#xff08;远程开机&#xff09; WOL Web# 访问 Wake on Lan Over The Interweb by Depicus 可以无需借助软件很方便的从网页前端唤醒远…

MATLAB / Simulink HDL 快速入门

MATLAB / Simulink HDL 快速入门 我们将使用实例讲解MATLAB / Simulink HDL 使用入门。 开始这个项目&#xff0c;首先需要创建一个包含 Stateflow 的新 Simulink 。只需单击画布中的任意位置并开始输入 Stateflow。 此时应该能在画布上看到 Stateflow 图标。双击图标进行编辑。…

使用xlwings获取excel表的行和列以及指定单元格的值

import xlwings as xw app xw.App(visibleFalse) # 隐藏Excel wb app.books.open(文档1.xlsx) # 打开工作簿sht wb.sheets[Sheet1] # 实例化工作表1#获取行数和列数 rows_countsht.range(1, 1).expand().shape[0] cols_countsht.range(1, 1).expand().shape[1] print(row…

Unity 利用UGUI制作圆形进度条

在Unity中使用Image和Text组件就可以制作简单的进度条。 1、首先准备好一张环状的PNG图&#xff0c;如下图。 2、把该图导入Unity中并转换成精灵。 3、在场景中创建Image和Text组件&#xff0c;并把上图中的精灵拖到Image的Source Image中&#xff0c;其中Image组件中的Image …

数据采集中的基本参数

分辨率(resolution) 分度数量越多则分辨率越高&#xff0c;测量精度也越高 区间(range) 模数转换所能处理模拟信号电平的极限 应尽量使输入与此区间匹配&#xff0c;物尽其用 信号极限幅度集合 所测信号的最大值和最小值 应与输入信号的最大值和最小值相接近 LSB 最低有效…

[云原生案例2.2 ] Kubernetes的部署安装 【单master集群架构 ---- (二进制安装部署)】网络插件部分

文章目录 1. Kubernetes的网络类别2. Kubernetes的接口类型3. CNI网络插件 ---- Flannel的介绍及部署3.1 简介3.2 flannel的三种模式3.3 flannel的UDP模式工作原理3.4 flannel的VXLAN模式工作原理3.5 Flannel CNI 网络插件部署3.5.1 上传flannel镜像文件和插件包到node节点3.5.…

springboot内容协商

1.基于请求头 Accept: application/json Accept: application/xml Accept: application/xxx 自定义数据 发的请求头的数据类型 期望返回的数据类型 2.通过请求参数 例如 /football?formatjson 一般respondbody 默认以json方式进行返回 如何请求同一个接口&#xff0c;可以…

软件测试Triangle练习题

软件测试Triangle练习题 待测类如下: package net.mooctest; public class Triangle {protected long lborderA = 0;protected long lborderB = 0;

vue中实现千位分隔符

vue中实现千位分隔符有两种&#xff0c;一种是某一个字段转换&#xff0c;一种是表格table中的整列字段转换 比如将3236634.12&#xff0c;经过转换后变为 3,236,634.12 1. 某一个字段转换 写js方法&#xff1a; export function numberExchange(value){if (!value) return…

Go 接口:Go中最强大的魔法,接口应用模式或惯例介绍

Go 接口&#xff1a;Go中最强大的魔法,接口应用模式或惯例介绍 文章目录 Go 接口&#xff1a;Go中最强大的魔法,接口应用模式或惯例介绍一、前置原则二、一切皆组合2.1 一切皆组合2.2 垂直组合2.2.1 第一种&#xff1a;通过嵌入接口构建接口2.2.2 第二种&#xff1a;通过嵌入接…