当前位置:网站首页>LeetCode-从链表中删去总和值为零的连续结点
LeetCode-从链表中删去总和值为零的连续结点
2022-08-09 04:14:00 【Master_hl】
目录
1.题目描述
题目要求

示例分析

提示

2.解题思路
准备工作:
1.从示例一的输入输出,我们很容易就想到了前缀和,通过一个 sum 变量就能知道什么时候需要做删除操作。
2.删除链表总和为 0 的结点,头结点也存在被删除的可能,所以我们需要一个辅助结点,来帮助我们进行删除操作。
分析解法:

示例1 提供的两种输出结果,其实间接的告诉了我们此题至少两种做法。
2.1 思路一:[前缀和 + 哈希表]
示例1 的输出结果如果是 [3,1],我们可以联想到哈希表。

1.从上图上,我们发现 sum 在加加的过程中,如果存在总和为 0 的结点,那么中间一定有两次 sum 的值相同,交叉出现相同的值,我们只关心前面那个值(例如上图 3 也重复出现了,但是 0 比 3 先出现,并且在将两个 0 之间的值删除后,3 就只剩下一个了)。
2.既然需要删除,又有相同的值,而哈希表恰好具备这些特点,当 key 值相同的时候,就会产生覆盖的效果,而这种效果如果放在链表中,那么刚好可以做到删除!!
3.于是,我们的思路是:将 ListNode.val 作为哈希表的 键(key),将 ListNode 作为哈希表的 值(val)。我们再添加 key 值得时候,就可以将 sum 添加进去;取值得时候,我们依旧按照链表得顺序来取,假设我们此时取出一个值为 0 ,此时的 0 就已经不再是 0x99 这个结点了,而是 0x33 这个结点了。(结合上图理解)
代码示例
class Solution {
public ListNode removeZeroSumSublists(ListNode head) {
HashMap<Integer,ListNode> map = new HashMap<>();
ListNode newHead = new ListNode(0);
newHead.next = head;
int sum = 0;
ListNode cur = newHead;
while(cur != null) {
sum += cur.val;
// map在添加元素的时候,key值相同,结点就会覆盖,就意味着前一个 key 一直加到后一个 key 的结果为 0
// 这也是为什么 node.val 作 key 的关键
map.put(sum,cur);
cur = cur.next;
}
sum = 0;
cur = newHead;
while(cur != null) {
sum += cur.val;
// 当后面的 key 值出现与前面的相等时,通过改变指针指向就可以删去中间的结点
cur.next = map.get(sum).next;
cur = cur.next;
}
return newHead.next;
}
}复杂度分析
时间复杂度:O(N),遍历两次链表,空间换取时间。
空间复杂度:O(N)
2.2 思路二:[前缀和+"双指针法"]
示例2的输出结果如果是 [1,2,1],那么我们就可以使用 "双指针法"。
输出这个结果,无非就是让 -3 和 3 相加变为 0 。此处多加一组示例 [1,2,3,-3,1] 便于后续对比理解。
此处的 "双指针法",并不是两两指针一起走,而是分别控制内外两层循环。并且此处的删除条件就仅仅是 sum = 0,不再是出现相同的和。
1.我们申请一个结点 prev 指向 newHead(不指向 head, 是因为如果出现 sum = 0 的时候,prev 和 cur 刚好指向同一个结点,那就没法进行删除了)。
2.申请一个结点 cur 指向 head,不断往后计算链表的前缀和。
cur 在每一轮循环计算前缀和的时候,会存在两种情况:
- cur 在遍历链表计算前缀和的过程中遇上了 sum = 0,可能在链表末尾,也可能在链表中间
- cur 在遍历链表计算前缀和的过程中没有遇上 sum = 0,但是不代表链表中没有和为 0 的结点。所以控制外层循环的指针需要往后走一步,cur 内层循环进行下一次判定。(不断缩小 cur 遍历链表的范围)
画图理解上述两种情况:
情况一

情况二:

代码示例
public ListNode removeZeroSumSublists1(ListNode head) {
ListNode newHead = new ListNode(0);
newHead.next = head;
ListNode prev = newHead;
while(prev != null) {
ListNode cur = prev.next;
int sum = 0;
while(cur != null) {
sum += cur.val;
// 链表 val 加和为 0 的时候,说明此时 prev 后面的数据,
// cur.next 之前的数据都需要删除
if(sum == 0) {
prev.next = cur.next;
break;
}
cur = cur.next;
}
// 1.如果内存循环正常走到链表末尾,则进行下一轮循环
// 2.如果内存循环结束的时候,cur 还没走到连链表末尾,说明此时在中途遇到 和为0 了
// 进行删除操作,并且这轮循环继续向下执行
if(cur == null) {
prev = prev.next;
}
}
return newHead.next;
}复杂度分析
时间复杂度:O(N^2),prev 每移动一次,cur 遍历一次链表。
空间复杂度:O(1)
本篇博客就到这里了,谢谢观看!
边栏推荐
- [Server data recovery] A case of data recovery when the Ext4 file system cannot be mounted and an error is reported after fsck
- 【Pyspark】udf使用入门
- 了解CV和RoboMaster视觉组(五)目标跟踪:概述与光流法
- 给电脑重装系统后修改远程桌面端口的方法
- 2022R1快开门式压力容器操作考试模拟100题及在线模拟考试
- 欧拉22.02系统 mysql5.7 arm版本的安装包, 哪里能下载到?
- 器件可靠性与温度的关系
- 阿里云天池大赛赛题(深度学习)——视频增强(完整代码)
- 33 Basic Statistics - One Item Nonparametric Test
- 761. 特殊的二进制序列(分治)
猜你喜欢
随机推荐
driftingblues靶机wp
union
Polygon zkEVM Prover
gopacket使用示例
阿里云天池大赛赛题(机器学习)——天猫用户重复购买预测(完整代码)
松柏集(云衣裳)
助力To B业务,这类企业端数据值得风控童鞋关注
数量遗传学遗传力计算1:亲子回归方法
了解CV和RoboMaster视觉组(五)运动建模与预测
Device Reliability vs. Temperature
【图形学】19 光照模型(四、Blinn-Phong光照模型)
3年半测试经验,20K我都没有,看来是时候跳槽了...
32 基本统计知识——假设检验
2022高压电工考试试题及答案
数量遗传学遗传力计算2:半同胞和全同胞
31 basic statistical concepts
npm package.json
提升用户体验,给你的模态弹窗加个小细节
了解CV和RoboMaster视觉组(五)local-distribution汇聚方法
【Redis底层解析】跳跃表








