删去总和值为零的连续节点(前缀和)

删去总和值为零的连续节点(前缀和)

题目描述

​ 给你一个链表的头节点 head,请你编写代码,反复删去链表中由 总和 值为 0 的连续节点组成的序列,直到不存在这样的序列为止。删除完毕后,请你返回最终结果链表的头节点。

OJ链接 来源:力扣(LeetCode)

示例

image-20220203122725233

解决

题目翻译

由于题目比较难理解,所以首先将题目用通俗易懂的语言描述一下:

将链表中和为的0 子链删除,直到不存在和为0的子链。

如下图所示,由于子链3 -3和为0,所以,我们应当知道被断开子链表的前驱节点 2,将其连接到被断开子链表的后继节点 5。

image-20220203125052081

思路分析

​ 通过计算前缀和,我们可以发现。红色部分和为3,橙色部分和为0,红色部分加上橙色部分后和还是为3,所以橙色部分就是要被删除的子链

​ 如何删除呢?

​ 将红色部分的最后一个节点(要删除子链的前驱节点)连接到橙色部分最后一个节点的下一个节点(要删除子链的后继节点)即可。

image-20220203125957268

因此,我们可以一边遍历链表,一遍记录当前的和,如果之前存在这个和,那么就把他们中间的节点都断掉。

步骤

  • 利用map集合保存当前遍历节点cur及其前缀和sum
    • 如果map集合已经存在该前缀和,那么找到已存在的节点,让其连接到当前节点的下一节点,然后删除断开子链中各个节点的前缀和(更新map集合)
    • 如果map集合中不存在,那么将其加入

代码实现

public ListNode removeZeroSumSublists(ListNode head)
{
    HashMap<Integer, ListNode> map = new HashMap<>();
    ListNode newHead = new ListNode(0, head);
    map.put(0, newHead);
    ListNode cur = head;
    int sum = 0;
    while (cur != null)
    {
        sum += cur.val;
        if (map.containsKey(sum))
        {
            //1.删除子链
            ListNode subListPrev = map.get(sum);//获取要删除子链的前驱节点
            ListNode subListCur = subListPrev.next;//子链的遍历节点,初始值为子链的头节点
            subListPrev.next = cur.next;//将子链的前驱节点连接到当前节点的下一节点
            //2.更新map
            int subListSum = sum;//保存当前和
            while (subListCur != cur)//直到遍历到要删除子链的后继节点
            {
                subListSum += subListCur.val;
                map.remove(subListSum);//移除map中保存的子链前缀和
                subListCur = subListCur.next;
            }
        }
        else
        {
            map.put(sum, cur);//添加当前节点及前缀和
        }
        cur = cur.next;//指针后移
    }
    return newHead.next;
}
        }
        cur = cur.next;//指针后移
    }
    return newHead.next;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值