给你一个链表的头节点
head
,请你编写代码,反复删去链表中由 总和 值为0
的连续节点组成的序列,直到不存在这样的序列为止。删除完毕后,请你返回最终结果链表的头节点。
你可以返回任何满足题目要求的答案。
(注意,下面示例中的所有序列,都是对
ListNode
对象序列化的表示。)示例 1:
输入:head = [1,2,-3,3,1] 输出:[3,1] 提示:答案 [1,2,1] 也是正确的。示例 2:
输入:head = [1,2,3,-3,4] 输出:[1,2,4]示例 3:
输入:head = [1,2,3,-3,-2] 输出:[1]提示:
- 给你的链表中可能有
1
到1000
个节点。- 对于链表中的每个节点,节点的值:
-1000 <= node.val <= 1000
.
反复删除链表中总和为0的连续节点组成的序列 使用前缀和和哈希表解决
前缀和是指从头结点一直到当前结点之间结点的和,通过计算每个结点的前缀和记录到哈希表中,使用前缀和作为key,使用当前结点作为value,如果有前缀和相同的两个结点则说明这两个结点之间的和为0,也就是可以删除的序列。
例如 1,2,3,-3,-2,4 这个序列,在第0个结点的前缀和为1,之后的2,3,-3,-2这个序列的结点的和为-0,到第4个结点(值为-2的结点)的前缀和为1,两个前缀和相同,只需要将第0个结点的next指针指向第4个结点的下一个结点就可以删除这四个和为0的结点。
public ListNode removeZeroSumSublists(ListNode head) {
ListNode dummy = new ListNode(0); //头节点,指向链表的头节点
dummy.next = head;
HashMap<Integer, ListNode> seen = new HashMap<>();//哈希表中的key为前缀和,value为当前结点
int prefix = 0;
for (ListNode node = dummy;node != null;node = node.next){//循环遍历链表
prefix += node.val; // 计算当前节点的前缀和
seen.put(prefix,node);//放入哈希表中
}
prefix = 0;
for (ListNode node = dummy;node != null;node = node.next){//第二次遍历,找出相同前缀和并删除
prefix += node.val; //计算前缀和
node.next = seen.get(prefix).next;//,找出哈希表中相同前缀和的结点,删除序列
}
return dummy.next;//返回删除后的链表的头节点
}