代码随想录|704.二分查找、27.移除元素

代码随想录算法训练营Day01 | 704. 二分查找、27. 移除元素 阅读详情

数组

  1. 数组在内存中的表现是一段连续的空间,每一个地址都是相同的数据类型
  2. 增加或者"删除"(覆盖)操作,需要移动对应下标"之后"的所有元素

二分法

使用条件:有序数组,无重复元素
循环更改中位数,要注意判断区间在整个循环过程中应当保持一致。
比如[left,right],那么在更改的时候left = middle+1或者right = middle -1。右边界应当为size()-1。并且判断循环结束的条件为left>right
如果为[left,right)那么在更改的时候left = middle +1或者right = middle,右边界此时应当为size(),此时结束的条件为left>=right

leetcode704二分查找

文档讲解:代码随想录
视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找
状态:方法错误,不能全过

  1. 自己的思路
    用middle和数组长度作为判断和循环终止条件。会出现很多问题,首先是对于头和尾的元素无法考虑进去,且middle是通过数组长度/2得到的整数,可能会丢弃掉某些值

  2. 二分查找思路
    注意到题目中,升序(有序)并且无重复的两个条件,所以可以考虑二分查找方法。
    在使用二分查找方法的过程中,需要注意循环终止条件和中值的变换要保持一致以及相互对应。
    下方为使用[left,right]的方法解决,得到时间复杂度为O(logN)。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int length = nums.size()-1;
        int left = 0;
        int right = length;
//如果是[left,right),right = length+1 ,left<right , right = middle;

        while(left <= right)
        {
            int middle = (right+left)/2;

            //此时中位数小,说明target在右边,更新left,计算middle
            if(nums[middle] < target)
            {
                left = middle+1;
            }
            else if(nums[middle] > target)
            {
                right = middle-1;
            }
            else
            {
                return middle;
            }
        }
        return -1;
    }
};

leetcode35搜索插入位置

文档讲解:代码随想录
状态:对于头和尾的插入

  1. 思路
    看到有序和无重复,相当二分查找。本题遇上题不一样的是需要将-1变为要插入的位置。
    本题使用的左闭右开的方法,所以我们的判断区间是[left,right)。right即是我们的middle值,也是我们需要插入的位置。
    如果我们要插入的是头部,那么此时的区间为[0,0),如果我们要插入的是尾部那么此时的区间也是[left,right==nums.size()),所以最后返回的下标也是right。
    得到时间复杂度O(logN)
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int length = nums.size();
        int left = 0;
        int right = length;

        while(left < right)
        {
            int middle = (left+right)/2;
            if(nums[middle] < target)
            {
                left = middle+1;
            }
            else if(nums[middle] > target)
            {
                right = middle;
            }
            else
            {
                return middle;
            }
        }
        //如果没有则进行插入操作
        //插入后,后面元素需要向后移动
        //我们需要判断如果target插入到头和尾的时候
        //如果是头[0,0)
        //如果是尾[left,right)
        return right;
    }
};

在排序数组中查找元素的第一个和最后一个位置

文档讲解:代码随想录
状态:边界状态的判断

  1. 本题最大区别就是存在重复数据了,返回的是一个数组,可以将else中的return变为将开始位置和结束位置添加到数组里面
  2. 我们使用了分别判断左边界和右边界的方法,
    获取左边界,就相当于一直获取右范围,直到右范围对应的值小于了target,如果没有获得左边界的值,那么就说明target超过了这个数组的右端。
    获取右边界,就相当于一直获取左范围,直到左范围对应的值大于了target,如果没有获得右边界的值,那么就说明target小于这个数组的左端。
class Solution {
public:

    //获取左边界,同时判断target大于右边界的情况
    int GetLeftInd(vector<int>& nums, int target){
        int length = nums.size()-1;
        int left = 0;
        int right = length;
        int leftInd  = -2;
        while(left <= right)
        {
            int middle = (left+right)/2;
            if(nums[middle] >= target)
            {
                //leftInd的值会比正确的index小1
                right = middle - 1;
                leftInd = right;
            }
            else
            {
                left = middle+1;
            }
        }
        return leftInd;
    }

    //获取右边界,同时处理target小于左边界的情况
    int GetRightInd(vector<int>& nums, int target){
        int length = nums.size()-1;
        int left = 0;
        int right = length;
        int RightInd;
        while(left <= right)
        {
            int middle = (left+right)/2;
            if(nums[middle] <= target)
            {
                //rightInd的值会比正确的index大1
                left = middle + 1;
                RightInd = left;
            }
            else
            {
                right = middle-1;
            }
        }
        return RightInd;        
    }

public:
    vector<int> searchRange(vector<int>& nums, int target) {
        //定义一个返回数组
        int left = GetLeftInd(nums,target);
        int right = GetRightInd(nums,target);

        //当target小于最左值,或者大于最右值时候
        if(left == -2 || right == -2)
        {
            return {-1,-1};
        }
        else if(right-left>1)
        {
            return {left+1,right-1};
        }
        else
        {
            return {-1,-1};
        }
    }
};

X的平方根

  1. 二分法
    相当于从0到x的整数范围内寻找最大的那个整数a使得a*a<=x。注意到该数组序列是一个升序的,然后无重复的序列。不断的去寻找中间值a。
class Solution {
public:
    int mySqrt(int x) {
        int left = 0;
        int right = x;
        int res = -1;

        while(left <= right)
        {
            int middle = (left+right)/2;
			//long long为leetcode给的数据
            if((long long)middle * middle > x)
            {
                right = middle -1;
            }
            //当middle*middle<=x时,才可能得到正确的整数平方根
            //但还是不够,因为可能得到较小值,直到left和right相遇。
            else
            {
                res = middle;
                left = middle + 1;
            }
        }
        return res;
    }
};

由于题意是middlemiddle <= x的middle所以应当在使用左值返回,如果找middlemiddle>=x的数,那么应当使用right+1返回

有效的完全平方数

  1. 与上题一样,同样使用二分法,只不过需要更改判断条件,只有a*a == x的时候返回true,其余情况返回false。
class Solution {
public:
    bool isPerfectSquare(int num) {
        int left = 0;
        int right = num;

        while(left <= right)
        {
            int middle = (left+right)/2;
            if((long long) middle*middle > num)
            {
                right = middle-1;
            }
            else if((long long) middle*middle < num)
            {
                left = middle+1;
            }
            else
            {
                return true;
            }
        }
        return false;
    }
};

移除元素

文档讲解:代码随想录
视频讲解:《代码随想录》算法视频公开课 (opens new window):数组中移除元素并不容易!LeetCode:27. 移除元素
状态:暴力解法

  1. 暴力解法
    双重循环,第一重循环用于寻找判断当前下标是否与要删除的值相等,第二重循环用于将当前下标的之后的数向前移动,更新数组。
    要注意在第二重循环中,要注意当更新数组后,同时要更新下标值和循环终止的长度。
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int length = nums.size();
        for(int i=0;i<length;i++)
        {
            if(nums[i] == val)
            {
                for(int j = i;j<length-1;j++)
                {
                    nums[j] = nums[j+1];
                }
                i--;//i之后的值下标都减一了
                length--;//数组长度也要减少
            }
        }
        return length;
    }
};
  1. 双指针
    通过一个快指针和慢指针在一个for循环下完成两个for循环的工作
    快指针:寻找新数组的元素,新数组就是不含有目标元素的数组
    慢指针:指向更新,新数组下标的位置

快指针带动慢指针移动

在本题中,
快指针用于判断当前指向的数是否是要删除的数,如果是,移动快指针,保持慢指针。
慢指针用来存储新数组的下标,就是当快指针指向的值不是要删除的值,那么将慢指针指向的值更新为快指针指向的值。
如果是删除的值,那么就不做处理,只是移动快指针。

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

双指针的解题一般为

//循环体
	//判断,本文是判断不等的所以if不等,如果保留相等的,那么就是if相等
	//判断的条件需要和题目相同即是同一个真命题,如果是否命题那又要用一个循环来判断并且更复杂
		//慢指针移动+题目要求操作,只在满足题目需求是才能移动
	//快指针移动,不论什么情况都要移动
//
非华为设备实现多屏协同:最新电脑管家破解安装指南 本文提供了在非华为电脑上安装华为电脑管家并实现多屏协同功能的详细破解指南。通过绕过硬件检测机制,用户可在联想、戴尔等设备上体验与华为生态类似的无缝文件拖拽、跨屏操作等功能。文章涵盖了从系统准备、工具下载、破解安装到手机连接及故障排查的全流程,助您打破设备壁垒,提升办公效率。 阅读详情

相关推荐

20道SpringSecurity常见面试题汇总(超详细回答 !!!)

本文中,我们将探讨一些与 Spring Security 相关的面试问题。Spring Security 是一款流行的 Java 应用程序安全框架,它提供了一套全面且易于使用的安全解决方案。

小斜同学的博客 3076

代码随想录算法训练营第一天 | 704. 二分查找、27. 移除元素

代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素

北天的博客 1158

深度学习模型设计的方法和技巧

设计神经网络模型是一个迭代的过程,需要不断试验和调整各个组成部分,以达到最佳性能。同时,遵循良好的工程实践,如模块化设计、版本控制、文档记录等,也是成功的关键。

xw555666的博客 4027

代码随想录算法训练营Day 1 | 704. 二分查找、27. 移除元素

数组是存储在连续的内存空间相同类型数据的集合。通过下标索引获取下标对应的数据。2.注意:1)下标从0开始;2)数组内存空间的地址连续因为数组在内存空间地址连续,所以在增删元素的时候,需要移动其他元素的地址。3.数组元素不可以删除,只能覆盖。

loveJava17的博客 930

从“看不懂Sansen”到亲手搭建:一个Class AB输出级+浮动电压源的保姆级设计复盘

本文详细记录了从理论困惑到实践突破的Class AB输出级与浮动电压源设计全过程。通过电流镜调试、恒定跨导优化及版图匹配等关键步骤,作者实现了高性能运放设计,并分享了从仿真到实测的宝贵经验,为模拟电路初学者提供实用指导。

weixin_33737774的博客 867

ubuntu18.04安装R——无法连接上 dl.google.com:80 (6.6.6.6),连接超时&&E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。

安装R的时候,sudo apt update 的时候出现错误: 查资料要修改/etc/apt/sources.list.d/google-chrome.list 文件 原来是: deb http://dl.google.com/linux/chrome/deb/ stable main 改为: deb [arch=amd64] http://dl.google.com/linux/chrom...

许希律的博客 4350

代码随想录打卡打一天|704.二分查找,27.移除元素

力扣打卡

weixin_56718399的博客 1050

01-嵌入式入门-如何看原理图

最近由于找到的工作是偏于嵌入式方向,因此又重新开始学习已经丢弃两年的知识。新手学习知识感觉有一个通病:喜欢收集各种各样的视频、资料,网盘里收藏一大堆,但是却从没有打开看过,到头来还是个小白,只听说过几个概念,而实际却是不知所云,这就是所谓的"学习综合征"。而我也是其中的一员,最近痛定思痛,就准备根据一套资料沉下心学习下去,不再进入收集资料的大军。...

weixin_34010566的博客 4484

代码随想录Day1 | 数组理论基础、704. 二分查找、27. 移除元素

对于二维数组如何存放,不同语言不一样。比如C++就是连续存放的,而Java则不是。

m0_73617263的博客 749

一款值得关注的开源企业管理ERP系统

盒木ERP是一款开源的现代化企业管理系统,采用前后端分离架构,后端基于Python+Django,前端使用Vue+Ant Design。系统涵盖采购、销售、库存、财务等核心业务模块,支持移动端操作和PDA扫码。具有开源免费、技术先进、功能完善等特点,适合中小企业使用或二次开发。项目提供详细部署指南,支持Docker容器化部署,是学习ERP系统开发和企业数字化转型的优秀选择。

1107

详解FreeRTOS:事件标志组(高级篇—5)

事件组可以实现一对多,多对多的同步,即一个任务可以等待多个事件的发生。任务可以通过设置事件位来实现事件的触发和等待操作,FreeRTOS的事件仅用于同步,不提供数据传输功能。

不脱发的程序猿 1075

代码随想录算法训练营第一天|leetcode704.二分查找、27.移除元素

代码随想录训练营第一天打卡

m0_74360161的博客 256

69、SAP数据库归档重做日志备份策略与工具详解

本文详细解析了SAP数据库归档重做日志备份的重要性及策略,介绍了SAP提供的备份工具brarchive及其配置和使用方法,探讨了BRBACKUP与BRARCHIVE的联合运行、一致在线备份、备用数据库备份场景以及备份策略的综合应用与优化。此外,还分析了备份过程中常见问题的解决方法、备份监控与评估流程、与第三方备份解决方案的集成方式,以及未来备份技术的发展趋势和应对策略。通过合理运用这些策略和工具,可以有效保障SAP数据库的安全性和可恢复性。

peace的博客 135

代码随想录Day1|704.二分查找、27.移除元素、977.有序数组的平方

先前有一定的基础,题目做起来还算顺利。第一天在配置VScode相关环境以及学习如何写博客上花了比较多的时间,写博客也能有再一次的机会再理顺思路,巩固理解。

sleepwhite的博客 693

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

代码随想录算法训练营第一天 | 704. 二分查找 、 27. 移除元素

这个思想其实贯穿了整个代码随想录,扩展一下就是。

weixin_53416771的博客 735

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素

因为想着把两个指针的挪动都包在一个个i的for循环里,,所以在p和q++放的位置这里思考了很久,是先挪呢还是先判断呢,是把q++放到判断里呢还是判断外呢,好像总是想不出来一个满足所有特殊情况的做法。思路是:快指针采用for进行循环,一直在往后移,快指针还没遇到需要移除的元素的时候,q指针会跟着往后挪,不断的把旧数组中的元素放进新数组中。当快指针找到需要移除的元素时,慢指针就不会跟着快指针进行挪动,直到找到下一个可以更新的元素。这样,也就不用管p远离q很远了,反正遇到不移除的q更新就好了。

studingbear的博客 822

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

代码随想录算法训练营第一天 704. 二分查找 27. 移除元素977.有序数组的平方

内容较为简单。有几个小问题。704. 二分查找注意左闭右闭和左闭右开两种写法,想清楚边界问题。27. 移除元素思路上有一个巧点,用双指针,而不是暴力。977.有序数组的平方思路上有一个巧妙的地方,首先,肯定不是暴力,有一些方法,比如双指针。其次,双指针其实有不同的用法,比如:(1)指向0左右的最靠近0的正负数,向两边移动。新创建的用来放结果的数组中,指针从后往前走。(2)从两边开始,到中间会和。新创建的用来放结果的数组中,指针从前往后走。

2301_80094768的博客 957

代码随想录Day1|数组理论基础,704. 二分查找,27. 移除元素,977.有序数组的平方

在数组中,删除某一个数是不可行的,因为数组是一个连续空间的集合,删除某一个数后,该数值的空间位置仍然存在。因此要选择覆盖函数。采用双指针解法,slow指针赋予新数组的地址空间,然后fast用于查找需要放入slow指针的值。迈开了写算法的第一步,坚持下去!!!!!

爱因斯小柚的博客 790

代码随想录算法训练营day01| 704. 二分查找、27. 移除元素

今日收获,记录一下自己的学习时长:可能自己还没有找到合适的方法,看完视频之后一下就写出来了,不知道这是不是背代码。自己看到题目的第一想法:第一次刷题,一切从头开始,看到题只想着简单遍历一下,发现是考察二分查找法(╥╯^╰╥)看完代码随想录之后的想法 :先跟着敲,记一下正确思路。选择左闭右闭的方法。自己看到题目的第一想法:两个for循环,超出时间限制。今日收获,记录一下自己的学习时长:一个半小时。自己实现过程中遇到哪些困难。自己实现过程中遇到哪些困难。看完代码随想录之后的想法。

m0_73945702的博客 356

代码随想录day1| leetcode704. 二分查找,35.搜索插入位置 ,27. 移除元素,977.有序数组的平方

看不懂。

weixin_44367813的博客 1065

【代码随想录|数组704. 二分查找,27. 移除元素】

代码随想录 python 数组

daisyholly的博客 876

代码随想录算法训练营第一天|LeetCode704. 二分查找,LeetCode27. 移除元素,LeetCode977. 有序数组的平方

思路:在数组两头分别设一个指针,然后让target和nums[mid]相比较,如果小于,则将右指针的范围缩到mid的左边,也就是r=mid-1,并重新设一次mid;如果大于,同理。如果等于则返回当前mid的下标。如果在循环条件结束之前依然没有搜索到,则返回-1。

Liverpool0519的博客 1212

代码随想录算法训练营第一天 | 704. 二分查找、 27. 移除元素、977.有序数组的平方

704. 二分查找给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。最简单的思路就是用一个循环暴力查找。这是使用二分法的前提,本题用二分法也更省时间。二分法并不难,但要关注边界处理,即要定义我们所找的目标元素target是处在一个[left,right]闭区间,还是处在(left,right]或[left,right)这种区间之中。

m0_52651829的博客 864

代码随想录算法训练营Day1(LeetCode704二分查找;LeetCode27移除元素;LeetCode977 有序数组的平方)

这道题和二分法一样,需要理解好区间,因为有了二分查找的思路,这道题很快就AC了,不过看了题解还是有一些新的感受。看到这道题,之前做过啊,那么最简单就是平方再排序,不过也可以双指针解法,因为数组呈现中间小两边大的趋势。实际做的时候,还是出现了比较多的索引越界之类的错误,一定要注意。这道题没理解原地移动,初步的思路是将相同的元素与末尾交换,但是这样就需要新的元素。的概念,也就是说需要知道循环中的区间是什么意思,这里每次的区间就是搜索区间,这样来看。的更新取值还是写错了,之后看了讲解思路,强调了。

weixin_51001256的博客 710

代码随想录算法训练营第一天|LeetCode704 二分查找、LeetCode27 移除元素、LeetCode977 有序数组的平方

有些代码写的有点重复目前只会使用最简单方法解题,尽可能考虑时间复杂度有时间了解一下排序算法今日两种双指针法都降低了时间复杂度,以后可以考虑使用场景(什么时候能使用双指针法)三道题目:循环区间不变量、快慢指针法、双指针法。

weixin_46078957的博客 579

代码随想录算法训练营第一天 | 704.二分查找 27.移除元素 977.有序数组平方

704. 二分查找文章讲解:代码随想录视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili思路:设置left,right下标初始值,while区间循环,mid指向(left+right)/2;目标值target<nums[mid],目标值在mid左半部分,改变right将区间缩小到左半部分;目标值target>nums[mid],目标值在mid右边半部分,改变left将区间缩小到右半部分;目标值target=nums[mi

m0_50413530的博客 709
上一篇: hexo+github搭建博客后发布文章访问时显示404的一种情况
下一篇: 代码随想录Day2| 977.有序数组的平方209.长度最小的子数组 59.螺旋矩阵II
sRiddle
博客等级 码龄7年 528粉丝 63原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值