您现在的位置是:首页 >技术杂谈 >LC-1171. 从链表中删去总和值为零的连续节点(模拟,哈希表+前缀和)网站首页技术杂谈

LC-1171. 从链表中删去总和值为零的连续节点(模拟,哈希表+前缀和)

Miraclo_acc 2024-10-07 12:01:05
简介LC-1171. 从链表中删去总和值为零的连续节点(模拟,哈希表+前缀和)

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

难度中等208

给你一个链表的头节点 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]

提示:

  • 给你的链表中可能有 11000 个节点。
  • 对于链表中的每个节点,节点的值:-1000 <= node.val <= 1000.

模拟

class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        ListNode dummy = new ListNode(0, head);
        while(true){
            ListNode pre = dummy;
            boolean flag = false;
            // 枚举每个点 pre 作为起点,查看从pre到cur是否存在 和为0 的连续区间
            while(pre != null && pre.next != null){
                ListNode cur = pre.next;
                int sum = cur.val;
                while(cur.next != null && sum != 0){
                    cur = cur.next;
                    sum += cur.val;
                } 
                // 存在和为0 的连续区间,直接删除[pre+1, cur]这一段
                if(sum == 0){
                    pre.next = cur.next;
                    flag = true;
                }
                pre = pre.next;
            }
            // 找不到和为0 的连续区间,停止循环
            if(!flag) break;
        }
        return dummy.next;
    }
}

时间复杂度:O(n^2),由于存在区间和为0的话,直接删除,所以时间复杂度和遍历节点个数有关?

空间复杂度:O(1)

哈希表

存前缀和,然后遍历找已经存在的再删除。

若链表节点的两个前缀和相等,说明两个前缀和之间的连续节点序列的和为 0,那么可以消去这部分连续节点。

class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        Map<Integer, ListNode> map = new HashMap<>();

        // 首次遍历建立 节点处链表和<->节点 哈希表
        // 若同一和出现多次会覆盖,即记录该sum出现的最后一次节点
        int sum = 0;
        for (ListNode d = dummy; d != null; d = d.next) {
            sum += d.val;
            map.put(sum, d);
        }

        // 第二遍遍历 若当前节点处sum在下一处出现了则表明两结点之间所有节点和为0 直接删除区间所有节点
        sum = 0;
        for (ListNode d = dummy; d != null; d = d.next) {
            sum += d.val;
            d.next = map.get(sum).next;
        }

        return dummy.next;
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。