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

157 阅读1分钟

1.题目简述

存在一个链表,其头节点为 head。要求反复删去链表中总和值为 0的连续节点组成的序列,直到不存在这样的序列为止。

例子:

输入:head = [1,2,-3,3,1,2,2,2,-6,5]

输出:[3,1,5]

详情请查看 LeetCode 官网:1171. 从链表中删去总和值为零的连续节点 - 力扣(LeetCode)

2.方法

根据例子中链表的值,计算其前缀和([0, 1, 3, 0, 3, 4, 6, 8, 10, 4, 9]),可以得到如下的趋势图。从趋势图可知,节点 0 和 节点 3 其前缀和相同,节点 5 和节点 9 其前缀和相同。观察链表中的值,我们发现前缀和相同的序列总和值为 0,因此我们可以通过哈希表保存当前前缀和和当前节点的映射关系。

  • 可以知道从左往右遍历的过程中,前缀和相同的节点将会被后面的节点覆盖
  • 只需将第一次出现的前缀和的节点和第二次出现前缀和的节点的后继节点相连即可

idx  =[0,1,2,   3,4,5,6,7,8  ,   9,10]idx\ \ = [0, 1, 2, \ \ \ 3, 4, 5, 6, 7, 8\ \ , \ \ \ 9, 10]

head=[0,1,2,3,3,1,2,2,2  ,6,5  ]head= [0, 1, 2, -3, 3, 1, 2, 2, 2\ \ , -6, 5\ \ ]

pre  =[0,1,3,   0,3,4,6,8,10,   4,9  ]pre\ \ = [0, 1, 3, \ \ \ 0, 3, 4, 6, 8, 10, \ \ \ 4, 9\ \ ]

趋势图.png

说明:新建一个虚节点,值为 0,并且其指针指向头节点。从虚节点给每一个节点设置编码(idx),从 0 开始。

3.代码

public ListNode removeZeroSumSublists(ListNode head) {
    // 新建虚节点
    ListNode newHead = new ListNode(0);
    newHead.next = head;
    int prefix = 0;
    ListNode cur = newHead;
    Map<Integer,ListNode> seen = new HashMap<>();
    // 保存当前前缀和和当前节点的映射关系
    for(;cur!=null;cur=cur.next){
        prefix += cur.val;
        seen.put(prefix,cur);
    }
    prefix = 0;
    for(cur=newHead;cur!=null;cur=cur.next){
        prefix += cur.val;
        cur.next = seen.get(prefix).next;
    }
    return newHead.next;
}

例子执行图解:

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

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

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