0
点赞
收藏
分享

微信扫一扫

LeetCode 1171. 从链表中删去总和值为零的连续节点



文章目录

  • ​​题目描述​​
  • ​​思路​​
  • ​​代码​​
  • ​​扩展​​

题目描述

给定一个链表,请反复删去链表中和为​​0​​的连续序列,直到不存在这样的序列为止。

比如 ​​[1,2,-3,3]​​​, 可能的答案为 ​​[3]​​​,或者​​[1,2]​

思路

连续和为​​0​​​,连续和,容易想到前缀和。顺着前缀和来想,什么时候能够判断出一段连续序列的和为​​0​​​呢。只要2个位置的前缀和相等即可。比如链表为​​[1,2,3,-4,2,2]​​​, 算出其前缀和数组为​​[1,3,6,2,4,6]​​​。可以看到分别在第3,第6个位置上的前缀和,皆为​​6​​​。我们只需要删除第​​4​​​到第​​6​​个位置,即可。

也就是说,只要在从左往右遍历的过程中,出现了相同的前缀和,我们就要进行删除操作。由于我们操作的是链表,则需要一个​​Map​​来存储链表节点,​​Map​​的​​key​​为前缀和,​​value​​为链表节点。

我们只需要遍历链表,并累加计算前缀和,并每次判断当前前缀和的值,是否已存在,若是,则从​​Map​​从取出对应的节点,并删除2个节点之间的部分(注意需要将被删除的节点,从​​Map​​中移除)。

下面借​​这篇LeetCode题解​​中的图片来进行说明

LeetCode 1171. 从链表中删去总和值为零的连续节点_leetcode

LeetCode 1171. 从链表中删去总和值为零的连续节点_链表_02

特别注意:

  • 第一个节点可能是需要删除的节点,比如​​[1,2,-3,4]​​,所以我们需要一个虚拟头节点。
  • 当整个数组的连续和才为​​0​​​时,可能不存在重复的前缀和,比如​​[1,2,-3]​​​,前缀和为​​[1,3,0]​​​, 此时我们要将虚拟头节点也加入到​​Map​​​中,并且设其前缀和为​​0​

代码

class Solution {
public ListNode removeZeroSumSublists(ListNode head) {
ListNode hh = new ListNode(0, head);
Map<Integer, ListNode> map = new HashMap<>();
map.put(0, hh);
int sum = 0;
while (head != null) {
sum += head.val; // 当前位置的前缀和
if (map.containsKey(sum)) {
ListNode node = map.get(sum);
ListNode deleteBegin = node.next;
node.next = head.next; // 将中间部分切掉
int dSum = sum;
while (deleteBegin != head) {
// 从map中删除, 删除到head前一个节点, 注意不能删除head这个节点, 因为head节点本身没有被put进去
dSum += deleteBegin.val;
map.remove(dSum);
deleteBegin = deleteBegin.next;
}
} else {
map.put(sum, head);
}
head = head.next;
}
return hh.next;
}
}

扩展

另一种思路,不需要在遍历过程中维护​​Map​​的中间状态。但需要2次遍历。第一次遍历计算前缀和,并直接插入到​​Map​​,相同的前缀和的值,会被后面的节点覆盖掉。

第二次遍历时,计算前缀和,并判断该前缀和是否存在于​​Map​​中, 由于​​Map​​中存的都是最右侧的节点,则能保证删除的是最长的。删除之后,并不需要从​​Map​​中移除中间被删除的节点,因为对于后续的遍历,若出现了前缀和相同,则​​Map​​中的节点一定是当前节点更往右的,不可能出现在前面已被删除的部分。

这种思路的好处是,代码很好写

注意

  • 第二次遍历时,要从虚拟头节点开始。
  • 实际在判断​​map.containsKey(sum)​​​,并作链表切断时,做了很多无用的切断。比如根本不存在连续和为​​0​​​的序列,如​​[1,2,3]​​​。在第二次遍历时,每个节点的位置,都会遇到​​map​​​中存在这个前缀和的情况,都会做一次​​cur = cur.next​​ 这样的无效操作
class Solution {
public ListNode removeZeroSumSublists(ListNode head) {
ListNode hh = new ListNode(0, head);
Map<Integer, ListNode> map = new HashMap<>();
map.put(0, hh);
int sum = 0;
for (ListNode cur = head; cur != null; cur = cur.next) {
sum += cur.val;
map.put(sum, cur);
}
sum = 0;
for (ListNode cur = hh; cur != null; cur = cur.next) {
sum += cur.val;
if (map.containsKey(sum)) cur.next = map.get(sum).next;
}
return hh.next;
}
}



举报

相关推荐

0 条评论