Talentd
FleetCode
Make and follow sheets.Sign in

Remove Zero Sum Consecutive Nodes from Linked List solution and explanation

MediumHash TableLinked List6 min read53.3% acceptanceUpdated 9 Apr 2026
Remove Zero Sum Consecutive Nodes from Linked List | Made Super Easy | Leetcode-1171codestorywithMIK · 23:53 · 21K viewsWatch on YouTube
9 more videos on this problem
  1. Remove Zero Sum Consecutive Nodes from Linked List | Made Super Easy | Leetcode-1171codestorywithMIK · 23:53 · 21K views
  2. LeetCode 1171 | Remove Zero Sum Consecutive Nodes from Linked Listleetuition · 12:39 · 16K views
  3. 1171. Remove Zero Sum Consecutive Nodes from Linked List | Prefix Sum | Brute -to- OptimalAryan Mittal · 34:42 · 5K views
  4. 1171 Remove zero sum consecutive nodes from linked list | leetcode daily challenge | DSA | ShashwatShashCode · 20:24 · 2K views
  5. LeetCode 1171 | Remove Zero Sum Consecutive Nodes from Linked List | HashMap | PreSum | JavaSleepy Cracker · 7:55 · 1K views
  6. Remove Zero Sum Consecutive Nodes from Linked List || LeetCode 1171DSA Solutions · 14:57 · 1K views
  7. 1171. Remove Zero Sum Consecutive Nodes from Linked List (Leetcode Medium)Programming Live with Larry · 42:16 · 721 views
  8. LeetCode 1171 - Remove Zero Sum Consecutive Nodes From Linked List - PythonAlpha-Code · 12:43 · 450 views
  9. 1171. Remove Zero Sum Consecutive Nodes from Linked List | Prefix Sum + Hashing 🔥 | O(N) | C++Priyanshi Porwal · 20:43 · 309 views
  10. Leetcode 1171: Remove Zero Sum Consecutive Nodes from Linked ListAlgorithms Casts · 18:33 · 269 views

The problem

Given the head of a linked list, we repeatedly delete consecutive sequences of nodes that sum to 0 until there are no such sequences.

After doing so, return the head of the final linked list.  You may return any such answer.

(Note that in the examples below, all sequences are serializations of ListNode objects.)

Example 1:

Input: head = [1,2,-3,3,1]
Output: [3,1]
Note: The answer [1,2,1] would also be accepted.

Example 2:

Input: head = [1,2,3,-3,4]
Output: [1,2,4]

Example 3:

Input: head = [1,2,3,-3,-2]
Output: [1]

Constraints:

  • The given linked list will contain between 1 and 1000 nodes.
  • Each node in the linked list has -1000 <= node.val <= 1000.

Approach overview

Problem Overview: You are given the head of a linked list. If any consecutive sequence of nodes sums to 0, that entire sequence should be removed from the list. This removal can create new zero-sum sequences, so the process continues until no such segment exists.

Approach 1: Iterative Node Skipping (O(n²) time, O(1) space)

This approach repeatedly scans the list and checks every starting node to see whether a future sequence sums to zero. For each node, maintain a running sum while iterating forward. If the sum becomes 0, skip the entire range by adjusting the previous node’s next pointer. Because each node may trigger another forward scan, the algorithm can degrade to O(n²) time. The advantage is minimal memory usage since it only uses pointers and running sums without extra data structures. This approach helps you understand the mechanics of node removal in a linked list.

Approach 2: Prefix Sum Hash Map (O(n) time, O(n) space)

The optimal solution uses the prefix sum idea with a hash table. Traverse the list while maintaining a running prefix sum. If the same prefix sum appears twice, the nodes between those two positions must sum to zero. Store each prefix sum in a hash map pointing to the latest node where that sum appears. In a second pass, recompute prefix sums and update pointers so that each node skips directly to the next valid node stored in the map. This effectively removes all zero-sum segments in one sweep.

The key insight: identical prefix sums indicate a zero-sum range between them. Using a hash lookup reduces detection of these ranges to constant time, making the full traversal O(n). This pattern is common in problems involving cumulative sums and range detection, often discussed alongside hash map or linked list manipulations.

Recommended for interviews: The prefix sum + hash map approach is what most interviewers expect. The iterative method demonstrates that you understand linked list traversal and pointer manipulation, but the prefix-sum optimization shows stronger algorithmic thinking and familiarity with hash-based lookups that reduce quadratic scans to linear time.

Approach 1: Prefix Sum Hash Map

This approach uses a hashmap to record prefix sums while iterating through the linked list. When a prefix sum is repeated, it indicates that the nodes between the occurrences of the prefix sum form a zero-sum sequence.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def removeZeroSumSublists(self, head: ListNode) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head
        prefix_sum_map = {}
        prefix_sum = 0
        cur = dummy
        while cur:
            prefix_sum += cur.val
            if prefix_sum in prefix_sum_map:
                prev = prefix_sum_map[prefix_sum]
                node = prev.next
                p = prefix_sum
                while node != cur:
                    p += node.val
                    del prefix_sum_map[p]
                    node = node.next
                prev.next = cur.next
            else:
                prefix_sum_map[prefix_sum] = cur
            cur = cur.next
        return dummy.next
import java.util.HashMap;

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

public class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        HashMap<Integer, ListNode> map = new HashMap<>();
        int prefix = 0;
        for (ListNode cur = dummy; cur != null; cur = cur.next) {
            prefix += cur.val;
            if (map.containsKey(prefix)) {
                cur = map.get(prefix).next;
                int sum = prefix + cur.val;
                while (sum != prefix) {
                    map.remove(sum);
                    cur = cur.next;
                    sum += cur.val;
                }
                map.get(prefix).next = cur.next;
            } else {
                map.put(prefix, cur);
            }
        }
        return dummy.next;
    }
}
#include <unordered_map>
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* removeZeroSumSublists(ListNode* head) {
    ListNode* dummy = new ListNode(0);
    dummy->next = head;
    std::unordered_map<int, ListNode*> prefixSumMap;
    int sum = 0;
    for (ListNode* cur = dummy; cur != nullptr; cur = cur->next) {
        sum += cur->val;
        if (prefixSumMap.find(sum) != prefixSumMap.end()) {
            ListNode* prev = prefixSumMap[sum];
            ListNode* temp = prev->next;
            int p = sum;
            while (temp != cur) {
                p += temp->val;
                prefixSumMap.erase(p);
                temp = temp->next;
            }
            prev->next = cur->next;
        } else {
            prefixSumMap[sum] = cur;
        }
    }
    return dummy->next;
}
function ListNode(val, next = null) {
    this.val = val;
    this.next = next;
}

function removeZeroSumSublists(head) {
    let dummy = new ListNode(0);
    dummy.next = head;
    let prefixSumMap = new Map();
    let prefix = 0;
    for (let cur = dummy; cur !== null; cur = cur.next) {
        prefix += cur.val;
        if (prefixSumMap.has(prefix)) {
            let node = prefixSumMap.get(prefix).next;
            let sum = prefix;
            while (node !== cur) {
                sum += node.val;
                prefixSumMap.delete(sum);
                node = node.next;
            }
            prefixSumMap.get(prefix).next = cur.next;
        } else {
            prefixSumMap.set(prefix, cur);
        }
    }
    return dummy.next;
}
#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int val;
    struct ListNode *next;
};

struct ListNode* removeZeroSumSublists(struct ListNode* head) {
    struct ListNode *dummy = malloc(sizeof(struct ListNode));
    dummy->val = 0;
    dummy->next = head;
    struct ListNode *cur = dummy;
    int prefix_sum = 0;

    struct ListNode **seen = calloc(1001, sizeof(struct ListNode*));
    seen[0] = dummy;

    while (cur) {
        prefix_sum += cur->val;

        if (seen[prefix_sum]) {
            struct ListNode *node = seen[prefix_sum]->next;
            int p = prefix_sum;
            while (node != cur) {
                p += node->val;
                seen[p] = NULL;
                node = node->next;
            }
            seen[prefix_sum]->next = cur->next;
        } else {
            seen[prefix_sum] = cur;
        }

        cur = cur->next;
    }
    return dummy->next;
}
public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int x) { val = x; }
}

public class Solution {
    public ListNode RemoveZeroSumSublists(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        var prefixSumMap = new Dictionary<int, ListNode>();
        int prefix = 0;
        for (ListNode cur = dummy; cur != null; cur = cur.next) {
            prefix += cur.val;
            if (prefixSumMap.ContainsKey(prefix)) {
                cur = prefixSumMap[prefix].next;
                int sum = prefix + cur.val;
                while (sum != prefix) {
                    prefixSumMap.Remove(sum);
                    cur = cur.next;
                    sum += cur.val;
                }
                prefixSumMap[prefix].next = cur.next;
            } else {
                prefixSumMap[prefix] = cur;
            }
        }
        return dummy.next;
    }
}

In the Python solution, similar to others, a hashmap and a dummy node are used. The main loop calculates prefix sums and uses them to remove zero-sum subsequences.

Complexity

Time Complexity: O(n).

Space Complexity: O(n).

Try this approach in the editor

Approach 2: Iterative Node Skipping

This approach keeps processing the list until no zero-sum sublists can be found. This involves iterative rescanning of the list and skipping nodes accordingly.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def removeZeroSumSublists(self, head):
        dummy = ListNode(0)
        dummy.next = head
        removed = True
        while removed:
            cur = dummy
            sum = 0
            removed = False
            while cur.next:
                sum += cur.next.val
                if sum == 0:
                    cur.next = cur.next.next
                    removed = True
                else:
                    cur = cur.next
        return dummy.next
class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

public class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        boolean removed;
        do {
            ListNode cur = dummy;
            int sum = 0;
            removed = false;
            while (cur.next != null) {
                sum += cur.next.val;
                if (sum == 0) {
                    cur.next = cur.next.next;
                    removed = true;
                } else {
                    cur = cur.next;
                }
            }
        } while (removed);
        return dummy.next;
    }
}
#include <iostream>

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* removeZeroSumSublists(ListNode* head) {
    ListNode* dummy = new ListNode(0);
    dummy->next = head;
    bool removed = false;
    do {
        ListNode* cur = dummy;
        int sum = 0;
        removed = false;
        while (cur->next) {
            sum += cur->next->val;
            ListNode* node = cur->next;
            if (sum == 0) {
                cur->next = node->next;
                removed = true;
            } else {
                cur = cur->next;
            }
        }
    } while (removed);
    return dummy->next;
}
function ListNode(val, next = null) {
    this.val = val;
    this.next = next;
}

function removeZeroSumSublists(head) {
    let dummy = new ListNode(0);
    dummy.next = head;
    let removed = true;
    while (removed) {
        let cur = dummy;
        let sum = 0;
        removed = false;
        while (cur.next !== null) {
            sum += cur.next.val;
            if (sum === 0) {
                cur.next = cur.next.next;
                removed = true;
            } else {
                cur = cur.next;
            }
        }
    }
    return dummy.next;
}
#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int val;
    struct ListNode *next;
};

struct ListNode* removeZeroSumSublists(struct ListNode* head) {
    struct ListNode dummy, *cur, *node, *prev;
    int sum = 0, found;
    dummy.next = head;

    do {
        found = 0;
        cur = &dummy;
        sum = 0;
        while (cur->next) {
            sum += cur->next->val;
            node = cur->next;
            if (sum == 0) {
                cur->next = node->next;
                found = 1;
            } else {
                cur = cur->next;
            }
        }
    } while (found);

    return dummy.next;
}
public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int x) { val = x; }
}

public class Solution {
    public ListNode RemoveZeroSumSublists(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        bool removed = true;
        while (removed) {
            ListNode cur = dummy;
            int sum = 0;
            removed = false;
            while (cur.next != null) {
                sum += cur.next.val;
                if (sum == 0) {
                    cur.next = cur.next.next;
                    removed = true;
                } else {
                    cur = cur.next;
                }
            }
        }
        return dummy.next;
    }
}

The Python approach executes an iterative removal of zero-sum sequences by setting a flag, removing nodes, and repeating until no changes are necessary.

Complexity

Time Complexity: O(n^2).

Space Complexity: O(1).

Try this approach in the editor

Approach 3: Prefix Sum + Hash Table

If two prefix sums of the linked list are equal, it means that the sum of the continuous node sequence between the two prefix sums is 0, so we can remove this part of the continuous nodes.

We first traverse the linked list and use a hash table last to record the prefix sum and the corresponding linked list node. For the same prefix sum s, the later node overwrites the previous node.

Next, we traverse the linked list again. If the current node cur has a prefix sum s that appears in last, it means that the sum of all nodes between cur and last[s] is 0, so we directly modify the pointer of cur to last[s].next, which removes this part of the continuous nodes with a sum of 0. We continue to traverse and delete all continuous nodes with a sum of 0.

Finally, we return the head node of the linked list dummy.next.

The time complexity is O(n), and the space complexity is O(n). Here, n is the length of the linked list.

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function removeZeroSumSublists(head: ListNode | null): ListNode | null {
    const dummy = new ListNode(0, head);
    const last = new Map<number, ListNode>();
    let s = 0;
    for (let cur = dummy; cur; cur = cur.next) {
        s += cur.val;
        last.set(s, cur);
    }
    s = 0;
    for (let cur = dummy; cur; cur = cur.next) {
        s += cur.val;
        cur.next = last.get(s)!.next;
    }
    return dummy.next;
}
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeZeroSumSublists(head *ListNode) *ListNode {
	dummy := &ListNode{0, head}
	last := map[int]*ListNode{}
	cur := dummy
	s := 0
	for cur != nil {
		s += cur.Val
		last[s] = cur
		cur = cur.Next
	}
	s = 0
	cur = dummy
	for cur != nil {
		s += cur.Val
		cur.Next = last[s].Next
		cur = cur.Next
	}
	return dummy.Next
}
// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
//   pub val: i32,
//   pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
//   #[inline]
//   fn new(val: i32) -> Self {
//     ListNode {
//       next: None,
//       val
//     }
//   }
// }
impl Solution {
    pub fn remove_zero_sum_sublists(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let dummy = Some(Box::new(ListNode { val: 0, next: head }));
        let mut last = std::collections::HashMap::new();
        let mut s = 0;
        let mut p = dummy.as_ref();
        while let Some(node) = p {
            s += node.val;
            last.insert(s, node);
            p = node.next.as_ref();
        }

        let mut dummy = Some(Box::new(ListNode::new(0)));
        let mut q = dummy.as_mut();
        s = 0;
        while let Some(cur) = q {
            s += cur.val;
            if let Some(node) = last.get(&s) {
                cur.next = node.next.clone();
            }
            q = cur.next.as_mut();
        }
        dummy.unwrap().next
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Prefix Sum Hash Map

Time Complexity: O(n).

Space Complexity: O(n).

Iterative Node Skipping

Time Complexity: O(n^2).

Space Complexity: O(1).

Prefix Sum + Hash Table–

Complexity analysis

ApproachTimeSpaceWhen to Use
Iterative Node SkippingO(n²)O(1)Useful for understanding pointer manipulation and when minimizing memory usage matters
Prefix Sum Hash MapO(n)O(n)Best general solution. Detects zero-sum segments quickly using prefix sums and hash lookups

Frequently asked questions

Is Remove Zero Sum Consecutive Nodes from Linked List easy or hard?

The problem is rated Medium because it combines linked list pointer manipulation with the prefix sum technique. Developers familiar with prefix sums in arrays often find the concept straightforward, but applying it to linked lists requires careful pointer updates.

Remove Zero Sum Consecutive Nodes from Linked List Python/Java solution

Most implementations follow the same prefix sum logic across languages. Traverse the list, store prefix sums in a hash map mapping sum to node, then adjust node pointers in a second pass. This approach translates directly to Python, Java, C++, C#, and JavaScript.

How to solve Remove Zero Sum Consecutive Nodes from Linked List in O(n)?

Maintain a running prefix sum while traversing the list and store each sum in a hash map mapped to its latest node. If a prefix sum repeats, the nodes between the two occurrences sum to zero. Updating the previous node's next pointer removes the entire segment, allowing the algorithm to complete in linear time.

What is the best approach for Remove Zero Sum Consecutive Nodes from Linked List?

The most efficient approach uses prefix sums with a hash map. While traversing the linked list, store the latest node for each prefix sum. If the same prefix sum appears again, the nodes between them sum to zero and can be removed by updating pointers. This runs in O(n) time with O(n) extra space.

Is Remove Zero Sum Consecutive Nodes from Linked List asked at Google/Amazon/Meta?

Linked list problems involving prefix sums and hash maps are common in interviews at companies like Amazon, Google, and Meta. Variants of this problem test your ability to detect ranges using prefix sums and manipulate pointers efficiently in a linked list.

What data structure is used in Remove Zero Sum Consecutive Nodes from Linked List?

The optimal solution combines a linked list traversal with a hash map that stores prefix sums. The linked list handles node connections, while the hash map enables constant-time detection of previously seen sums to identify zero-sum ranges.

What is the time complexity of Remove Zero Sum Consecutive Nodes from Linked List?

The optimal prefix sum hash map solution runs in O(n) time because each node is processed a constant number of times. The space complexity is O(n) due to storing prefix sums in a hash map. A simpler iterative scanning approach exists but can take O(n²) time in the worst case.

Comments

Now write it yourselfClose this page and solve Remove Zero Sum Consecutive Nodes from Linked List in the editor, without looking.
Practise Remove Zero Sum Consecutive Nodes from Linked List