Leetcode刷题day1|数组一|704.二分查找,27.移除元素,35.搜索插入位置
创始人
2024-01-25 03:54:05
0

文章目录

    • 一、面试中数组相关理论知识
    • 二、二分查找问题
      • 思路
      • 注意事项
      • AC代码
    • 三、移除元素
      • 思路
      • 注意事项
      • AC代码
    • 四、寻找插入位置
      • 思路
      • AC代码
    • 五、总结
      • 二分法|二分查找法|二分搜索法|
        • 二分易错点
        • 相关概念
        • 代码实现

一、面试中数组相关理论知识

数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力。也就是说,想法很简单,但实现起来 可能就不是那么回事了。

要想真正理解数组在内存中的存储方式,就必须知道数组在内存中的存储方式。

重点就是数组在内存中的存储。

  1. 数组是存储在连续内存空间上的相同类型数据的集合。

  2. 数组的下标都是从0开始的

  3. 数组的内存空间的地址是连续的

  4. C++中二维数组在内存中也是连续的,java中没有指针,不对程序猿暴露元素的地址,寻址操作完全交给虚拟机,(即使打印也是经过哈希得到的虚拟地址)所以二维数组的每个元素【一维数组】内部可能是连续的,但是二维数组的元素之间可能不是连续的。

  5. 数组元素在内存空间中的地址是连续的,这就意味着我们在进行删除和添加元素的时候需要移动其他元素的地址。

  6. 数组的元素是不能删除的,只能进行覆盖

  7. 建议:能不能用库函数取决于用库函数是解决这个题目中的一小步,知不知道源码和源码实现以及时间复杂度,如果都是yes,那么可以使用,否则就是建议不用

二、二分查找问题

题目链接

思路

最基本的二分查找

注意事项

  1. 在while循环中,如果不是target值,除了修改left或者right值之外,还要修改mid的值。
  2. 对于mid的求法,需要用到一个数学技巧。不要直接right和left直接相加,而是用左端值+两者差值的一半。这样做的目的是为了防止right和left的和超出int所能表示的最大范围,导致溢出。

AC代码

class Solution {public int search(int[] nums, int target) {int left=0;int right=nums.length-1;int mid=left+(right-left)/2;while(left<=right){if(nums[mid]==target){return mid;}else if(nums[mid]left=mid+1;}else{right=mid-1;}mid=left+(right-left)/2;}return -1;}
}

三、移除元素

题目链接

思路

优化后的核心思路:双指针

因为此题要求空间复杂度为O(1),也就是说我们不能通过开辟临时数组来解题。那么很显然,这道题需要我们遍历数组,并进行原地修改数组,并且返回“新数组的长度”。

那么,我们应该怎样删除数组元素呢?

时间复杂度为O(n^2)

首先,移除也就是从把元素从数组中删除。但是我们知道数组其实不能从根本上删除元素,而是通过覆盖元素、同时**控制访问地址权限(即“修改数组长度”)**的方式来实现“删除元素的效果的”。

因此,我们可以通过设置cnt变量,初始值为0,来记录当前数组中需要删除的个数,并且在数组遍历的时候减去cnt个数。之后一满足条件就往前覆盖。

我们很容易写出这样的代码,但是它真的能ac吗?have a try.

public int removeElement(int[] nums, int val) {int cnt=0;for (int i = 0; i < nums.length-cnt; i++) {if(nums[i]==val){for (int j = i; j nums[j]=nums[j+1];}cnt++;}}return nums.length-cnt;
}

在这里插入图片描述

这是什么原因呢?我们调试看看是为什么

调试到这里我们可以发现,第一个2被删除了,但是紧挨的2并没有删除,此时就已经开始遍历下一个位置了。
在这里插入图片描述

很容易分析出来,是因为我们把后边的值往前拿了,但是后边的值到底是不是target值呢?我们不得而知。

倘若此时我们对代码不加修改,那么它就直接跳到下一个位置去了。相当于图示这种情况。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2WNqOsxp-1668578022005)(F:\typora插图\image-20221116114544401.png)]

因此,为了防止这种情况,我们在每次覆盖完成之后需要再次访问这个位置的元素,通过i–实现,看是不是target值。

这样写出的代码时间复杂度是O(n^2)、空间复杂度是O(1)

那么有没有办法将时间复杂度优化成O(n)呢?答案是肯定的

用双指针代替了一层for循环需要做的事情

慢指针是“新数组中的下标”,快指针是老数组中的不需要删除的元素对应的下标

int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {if (val != nums[fastIndex]) {nums[slowIndex++] = nums[fastIndex];}
}
return slowIndex;

注意事项

  1. 遍历的范围是0~nums.length-cnt
  2. 进行覆盖之后需要注意i–

AC代码

class Solution {public int removeElement(int[] nums, int val) {int cnt=0;for (int i = 0; i < nums.length-cnt; i++) {if(nums[i]==val){for (int j = i; j nums[j]=nums[j+1];}i--;cnt++;}}return nums.length-cnt;}
}

四、寻找插入位置

题目链接

思路

核心思路:二分查找/双指针

  1. 如果在原数组中存在,直接返回对应的位置,此时就等价于上边的二分查找
  2. 如果在元素中不存在,直接跳出循环,此时的left对应的下标恰好是对应的位置。

AC代码

class Solution {public int searchInsert(int[] nums, int target) {int left=0;int right=nums.length-1;int mid=left+(right-left)/2;while(left<=right){if(nums[mid]==target){return mid;}else if(nums[mid]>target){right=mid-1;}else{left=mid+1;}mid=left+(right-left)/2;}return left;}
}

五、总结

  1. 数组在内存中是连续存储的,不能够实现物理意义上的删除,只能实现逻辑上的删除元素。
  2. 逻辑删除元素的手段就是通过覆盖。
  3. 二分查找题目中需要注意每次访问后都需要改变mid的值
  4. 移除元素题目中需要注意每次覆盖后都需要i–,用于解决相邻待删除元素的问题,同时需要注意遍历的范围是在变化的。

二分法|二分查找法|二分搜索法|

二分易错点

1.while循环中的条件是left

2.当nums[mid]>target时,我们是更新左区间的右边界的,执行的操作是right=mid还是mid-1呢

相关概念

区间的类型

  1. 左闭右闭
  2. 左闭右开
  3. 左开右闭

区间的类型决定了上边两个易错操作究竟怎么处理 。在处理的边界时,我们需要坚持不变量。一开始是半开半闭,处理出来的结果也必须是半开半闭,反之,必须是全闭区间。

代码实现

左闭右闭

1.left可以等于right

  1. mid对应的大于target,那么应该是right=mid-1;
int left=0;
int right=nums.length-1;
int mid=left+(right-left)/2;
while(left<=right){if(nums[mid]==target){return mid;}else if(nums[mid]left=mid+1;}else{right=mid-1;}mid=left+(right-left)/2;
}
return -1;

左闭右开

  1. left不可以等于right【否则区间不合法】

  2. mid对应的大于target,区间中本来就不包含mid,那么是right=mid就可以了;

int left=0;
int right=nums.length-1;
int mid=left+(right-left)/2;
while(leftif(nums[mid]==target){return mid;}else if(nums[mid]left=mid;}else{right=mid;}mid=left+(right-left)/2;
}
return -1;

相关内容

热门资讯

人生的励志箴言 关于人生的励志箴言  1.朋友是雨中伞,遮风挡雨; 朋友是雪中炭,暖心驱寒;朋友是被中棉,温暖身心;...
不悔梦归处美文 不悔梦归处美文  今天去图书馆,一下午的时间看了点刘庸的《我不是教你祚》,晚上时也实在是无聊,又不想...
十部必看韩剧历史剧   大家看韩剧喜欢看韩国的历史剧吗?下文是励志网整理的十部必看韩剧历史剧,希望能帮助到你。  十部必...
青春奋斗带字励志图片   伟人之所以伟大,是因为他与别人共处逆境时,别人失去了信心,他却下决心实现自己的目标。下面是由yj...
古人关于描写云的励志诗句集锦 天空中又出现许多千变万化的云彩,时而像羽毛,轻轻地漂泊在空中;时而像羊群,缓缓地移动;时而像大海,翻...
校园励志电影 应届毕业生励志网分享15部校园励志电影:  1、律政俏佳人1、2(Legally Blonde)……...
生产管理励志口号 生产管理励志口号大全  1. 异常改善改善再改善,浪費减少减少再减少  2. 小问题,要重视,老毛病...
tvb励志电视剧2017   2017tvb新片巡礼剧有哪些?2017年tvb依然有好多好看的电视剧准备开播?下面我们一起来看...
励志江苏大龄考生陈洪涛 励志江苏大龄考生陈洪涛  参加16个专业自考  他还拥有多张资格证书  陈洪涛高中毕业后就去了扬州电...
青春励志女生合唱歌曲   导语:有哪些适合女孩子合唱的青春励志歌曲呢?以下是小编收集整理的青春励志女生合唱歌曲,希望大家喜...
青春励志人生小说   青春啊,难道你始终囚禁在狭小圈子里?你得撕破老年的蛊惑人心的网。今天励志网就为大家推荐一些青春励...
高考励志对联集锦   引导语:不知不觉,高考又要来到了,为了鼓励考生,下面unjs小编为大家带来关于高考励志的对联集锦...
四年级语文《徐悲鸿励志学画》... 四年级语文《徐悲鸿励志学画》教学反思  作为一名到岗不久的老师,我们的任务之一就是教学,对教学中的新...
励志歌曲集 励志歌曲之一腾格尔:大男人罗嘉良:创造晴天温兆伦:从未试过拥有Michael Learns To R...
初三班级励志誓词   导语:中考不相信“如果”,多一份勤奋,少一份后悔。在面对即将到来的高考,以下是小编整理的关于初三...
特深沉的人生感悟语句励志 特深沉的人生感悟语句【励志】  人生最重要的不是我们置身何处,而是我们将前往何处,特深沉的人生感悟语...
励志电影《土豪的情人节》推荐   土豪情人节又名土豪520。  《土豪520》是中国电影股份有限公司、江苏幸福蓝海院线有限公司、浙...
励志八字真言 励志八字真言  1、自加压力,敢于争先。  2、孜孜不倦,蒸蒸日上。  3、愚者千虑,必有一得。  ...
成功女人的励志故事 成功女人的励志故事  导语:谁说女子不如男?现在的女子可是个个都能够撑起半边天,事事靠自己。下面是小...
高三励志文章:高三,时间是赞... 高三励志文章:高三,时间是赞下来的    离2011年高考还剩下大约50天的时间了。    我们在复...