算法(数组+链表)

37.移除元素

数组的删除其实是元素的覆盖 比如刚开始五个元素删除了一个 他变成了四个元素 但是他的空间大小还是五

删除元素是o(n)erase的时间复杂度是o(n)

暴力实现

当使用两层for循环去删除元素的时候 

比如要删除元素三 但第一个for循环到数字三的时候 在第二个for循环中进行覆盖

双指针的实现

使用一层for循环解决

首先先定义一个快指针一个慢指针 快指针是指向新数组所需要的元素 需要更新的下标就是我们的慢指针 我们将快指针的值赋给慢指针

新数组是获取要更新的元素 慢指针是获取我们新数组中需要更新的位置

for循环中的if操作其实就是一个更新的操作 如果快指针等于val目标值 就不进行if 只有不相等的时候才进if 慢指针才++ 最后慢指针指向的是新数组的大小

977有序数组的平方

有序数组的话他如果有负数的话 是左右两边的平方大于中间的数 所以可以使用左右的双指针来往中间走

首先先定义一个数组 定义一个k=size-1也就相当于最后一个的下标值

将i放在左边 j放在右边 

然后进行比较 将平方的最大值放到k的位置 然后k--  途中可以简化代码 直接写k--

如果是i就向右++j的话就向左--

209长度最小的子数组

暴力思想

两层for循环

滑动窗口

我们使用滑动窗口的思想去解决

其实和双指针的思路差不多 只不过是我们取的是双指针中间的那块 就像一个滑动窗口

使用了一个for循环 做了两个for循环做的事情  

首先我们先思考一下for循环中的j 是起始位置的j还是终止位置的j

首先如果他是起始位置的j的话 终止位置 慢慢向右移动 最后得到数组看是否满足题目大小 这个其实和两个for循环的暴力思想差不多

所以这边的 j是终止位置的 起始位置的话 需要我们去利用一个动态移动去移动起始位置(精华)

for循环中的j已经确定了是终止位置 

起始位置的寻找: 当我们一步一步向右移动终止位置的时候 当找到集合中的大小大于等于s的时候 开始移动起始位置 这样就可以动态的收集不同区间里面的和 

题目讲解

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/minimum-size-subarray-sum/solutions/305704/chang-du-zui-xiao-de-zi-shu-zu-by-leetcode-solutio

59螺旋矩阵

在螺旋矩阵的时候四个角的边界点 不容易处理

我们要遵循一个循环不变量 就是对每条边处理的一个规则 是左闭右开还是什么 这个规则左闭右开就是只处理第一个节点 最后一个节点留给下一条边

还有就是他可以转几圈的问题 一般是n/2 如果n是奇数的话怎么办 当n为奇数的话都会留下中间的那个位置  我们只需要判断一下 n如果是奇数 我们对我们所填充的这个数组叫做numbers作为单独的数组 把最后的值赋给他就可以了

解决了转几圈 我们进入循环 我们要定义好起始位置 startx=0 starty=0 在定义一下offect=1 count=1

代码实现

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/spiral-matrix-ii/solutions/12594/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x

203移除链表元素

 头节点和中间节点的删除方式不一样 

中间的节点需要要前面的节点指向下一个节点

但是我们如果引入一个 虚拟的头节点 所有节点的删除方式就一样了

方法一(不引入虚拟)

判断头节点是否为为空 同时头指针指向的数值等于我们的target

这样的话只需要让head=head->next  

需要注意的一点就是 

这种情况 当把头节点删除的时候 他的下一个还是头节点 所以需要在上面的代码上加上while

头节点处理完之后 剩下的就是非头节点 定义一个cur指向head第一个节点 假如第二个节点是需要删除的元素 只需要 让cur指向cur的next的next就行 同时把cur的next删除 

同时要判断cur不能为空 和cur的next也不能为空 因为cur要指向下一个元素 为空的话 会报空指针异常 cur的next要和target进行作比较 如果他的next为空 又是操作空指针

方法二(虚拟头节点)

 new一个dummy head让dummy head指向head

定义一个cur去遍历链表 用cur=dummy head 如果cur的next不为空的话就用while去循环

然后cur的next=cur的next的next

如果没有找到我们的target cur就继续往下遍历 使用虚拟头节点的话 我们要return的就是dummy的next才是新链表的头节点 

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/remove-linked-list-elements/solutions/813358/yi-chu-lian-biao-yuan-su-by-leetcode-sol-654m

707设计链表

获取第n个节点的值

我们可以加入虚拟头节点 方便我们的增删查改

首先我们获取第n个节点的值 这个的话我们需要去判断n n如果小于0或者n>size-z则不满足条件

我们先定义一个cur用来遍历链表 让他直接指向dummy head的next 这边的话要注意以下边界的问题 比如cur的下一个指针为空的话 我们要直接返回当前的cur 否则会出现空指针异常

头部插入节点

首先 new一个新的节点 因为我们引入了虚拟的头节点 只需要讲new的节点放到两个节点之中就ok

这边有一个小坑就是在插入的顺序问题中 我们首先new出了新的节点 然后将dummy head 的next指向newnode  但是这边当这个操作之后 第三个节点就找不到了 因为之前dummy head 的next就是他 现在反而娶不到了

那么正确的顺序 是先new node 的next=dummy head 的next这样就可以获取到第三个节点 然后再让dummy head 的next指向new node

在尾部插入节点

我们先定义一个新的 节点 让cur=dummyhead

要让cur停到最后一个节点 他的循环条件就是 cur的next=null

第n个节点前插入节点

先定义一个cur让他等于dummy head 寻找第n个节点

 

这边直接将n放到了while循环中 并n-- 我们取一个极端的情况就是当n为0的时候 不进入循环 

那直接返回的就是dummy head的next 也就是第0个节点之前

我们要先new node的next指向cur的next再让cur的next=new node

删除第n个节点

cur=dummy head

要删除的第n个节点也就是cur 的next 可以假设n为0 并且只有一个节点那么不进入循环 删除的就是

cur的next也就是第一个节点

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/design-linked-list/solutions/1840997/she-ji-lian-biao-by-leetcode-solution-abix

206反转列表|双指针法|递归法

这道题我们可以使用双指针或者递归的解法

双指针

定义两个指针一个是cur一个是pre 

大体的过程就是将 cur指向pre

首先初始化的话就是cur=head pre=null

遍历的过程 什么时候算遍历结束   

当我们的cur指向了空指针的时候我们的pre指向的是尾节点 这个遍历的操作就结束了

 我们让cur指向了pre 但是我们怎么才能获取到 cur 的下一个节点这里的话我们就需要一个temp来进行一个暂存 没赋值之前 我们先将cur的next赋值给temp

然后cur=temp 最后新列表的头节点就是pre

递归

首先先有reverse 的函数 两个参数分别是cur 和pre 在主函数中调用reverse

主函数中给reverse 的两个参数 就分别是head 和null 

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-linked-list/solutions/551596/fan-zhuan-lian-biao-by-leetcode-solution-d1k2

24两两交换链表中的节点

思路

我们还是使用虚拟头节点的操作

在进行交换的时候 需要先将dummyhead节点指向2节点指向1节点指向三节点

这里经常犯空指针异常 或者是无限循环的错误

先定义一个虚拟头节点dummy head 指向head 

cur指针先指向dummy head 

这边的话链表中的节点可能有奇数个 也可能有偶数个 奇数个的话剩余最后一个就不做交换了 偶数的话正常进行一个交换

奇数情况下 cur 的next的next为null则结束

 

偶数情况下cur 的next为null则结束

代码书写的时候 这里要先写 保证cur的next不能为空 再写cur的next的next不能为空 如果写反的话可能先判断cur的next已经为空了 又进行了一个next 则空指针异常 所以这边的顺序是一个坑 把这两个条件放到while循环中

 cur的next的next赋值给cur的next 但是节点一的指针已经断了所以要在之前先把cur的next赋值给temp  temp1=cur的next的next的next 

之后再把temp赋值给cur的next的next

temp1赋值给temp的next 

紧接着需要去移动cur 直接往后移动两位就是cur的next的next

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/swap-nodes-in-pairs/solutions/444474/liang-liang-jiao-huan-lian-biao-zhong-de-jie-di-91

19删除链表倒数第n个节点

思路

这边很重要的一点就是 要删除倒数第二个节点的话需要我们去将cur放到倒数第三个节点上 这样才可以将前面的节点和被删除节点的后一个节点对接上

我们还是使用虚拟头节点dummy head

我们定义一个快指针 然后再定义一个慢指针 

可以先让快指针先移动n+1步 这样再同时移动快慢指针 这样当快指针指向null的时候 慢指针就指向要删除元素的前一位了

先快指针和慢指针都指向dummy 移动快指针的操作是n-- 

141环形链表

思路

判断有环否 可以使用一个快指针一个慢指针来看是否这两个指针可以相遇 快指针可以先走两个位置 慢指针每次走一个位置 这样快指针相对于慢指针就是一个位置 这样就可能快指针追上并等于慢指针 但是如果快指针一次走三个位置 慢指针一次走一个位置 相差两个位置的话 就可能会跳过慢指针

如何找到环的入口处 

这里其实有一个等式 假设快慢指针在y和z的交界点相遇 定义xyz

那么慢指针走的距离就是 x+y 快指针走的距离就是x+y+n(y+z) 因为慢指针到的时候快指针可能走了n圈了

因为快指针每次走两 慢指针走一 2(x+y)=x+y+n(y+z)

得到x=n(y+z)-y 那么x=(n-1)(y+z)+z 从这个式子中可以看出 n转几圈都无所谓 

x=z

在一个while循环中 判断条件就是快指针不能为空 和快指针的next不能为空 因为快指针是两个两个跳的 所以也要确保快指针的next也不能为空 

如果fast==slow i定义一个ndex1=fast index2 =head

while(index1!=index2)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值