算法训练营Day 1

数组

定义:

数组是存放在连续内存空间上相同类型数据的集合

注意事项:

数组下标从0开始

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

补充知识:内存地址

c++:

简单介绍一下, 0x7ffee4065820 与 0x7ffee4065824 差了一个4,就是4个字节,因为这是一个int型的数组,所以两个相邻数组元素地址差4个字节。

java:

java是没有指针的,数组地址也不会暴露给程序员,都是由虚拟机完成寻址操作,即便是打印出来的地址,也是经过处理之后的地址。

二分法(LeetCode704)

领域展开条件:(得到一个解题启示:学会收集条件,总结条件)

有序数组,元素不重复(保证得到唯一结果)

核心思路:

顾名思义,二分,把数组分为两部分(/2),得到数组的上下界,以及一个排在中间的元素及其索引,将中间元素与目标元素对比,如果中间元素大于目标元素,说明要把查询的区间缩小至左半边,反之缩小至右半边。

重点 / 易混淆:

while的循环条件

nums[middle] > target 时,right的处理

上述要点要结合起来说,while的循环条件就两种,循环条件不同,则对应的right处理不同:

第一种:left <= right

此时right赋值为 middle - 1,因为可以确定middle元素不是目标元素,且此时寻找的区间是左闭右闭,即查询区间会算上right,所以必须把确定不是的元素排除在外

第二种:left < right

此时right赋值为middle,同样的也确定了middle元素不是目标元素,而此时的寻找区间是左闭右开,即查询区间不会算上right,所以要保证还未查询的元素在查询范围内,则不能 -1

coding时遇到的问题:

我对于两个写法是先基于左闭右闭的写法,在此基础上改写成左闭右开的写法,想以此加深理解两种写法的区别。于是最开始只是将上述重点提到的处理改写了,却忽略了最开始的边界问题,即right如何确定。

right应当时刻覆盖未查找过的数组范围,我这么说可能不太准确,举个例子:只包含单个元素的数组,target就是数组中的元素

那么如果是左闭右开,初始的right就应当直接定为nums.length,这样才能保证数组不越界。而左闭右闭,初始的right就应当是nums.length - 1

对于《随想录》总结的理解:

问题的关键就在于区间定义,这是一个不变量,也是我们后续处理查找边界的重要准则。包括我上述遇到的问题,其实也是对于区间定义作为边界处理准则的原则理解得不够到位导致的。

移除元素(LeetCode29)

暴力解法:

遇到的问题:

忽略了在每次匹配到要删除的val之后,i要自减1,否则等于跳过了一个元素没有去做判断

忽略了每次删除之后,要对循环遍历的边界做修改,即自减1,否则如果数组最后几个元素都是目标元素,就会死循环

快慢指针:

快指针:用于遍历数组中的每一个元素

慢指针:指向的是新数组的下标的位置

执行流程:

快指针创建于遍历,慢指针则用于创建满足要求的新数组,当快指针指向的元素不等于要删除的元素,满指针就可以指向这个元素,并自增1。

双向指针:

左指针(leftIndex):从数组第一个元素开始,用于查找要删除的元素

右指针(rightIndex):从数组最后一个元素开始,用于查找不需要删除的元素

执行流程:

找到之后,将右指针指向的元素覆盖到左指针指向的元素,因为此题说明了不需要考虑元素的顺序,所以这种覆盖是被允许的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值