10

Given a list in form of linked list, I have to canceled out all the resources whose sum up to 0(Zero) and return the remaining list.

Like

6 -6 3 2 -5 4 returns 4
8 10 4 -1 -3 return 8 10

I only need algorithm to solve this question.

saurabh
  • 121
  • 1
  • 1
  • 5
  • in the second example if the input was `8 10 1 4 3 -1 -3` what would be the result? – eltonkamami Jul 24 '16 at 19:45
  • either 8 10 4 or 8 10 1 3 – saurabh Jul 24 '16 at 19:46
  • would be better if i could return smaller list. – saurabh Jul 24 '16 at 19:46
  • Will the items that sum to zero always be consecutive? I.e. will you always have `6 -6 3 2 -5 4` or can it also be `6 4 -5 3 -6 2`? Because your examples seem to satisfy the first case in which case the "dumbest" algorithm is probably "only" `O(n^2)` (for each starting index `i`, loop through the remainder of the list until you reach the end or find a zero-sum subset). – CompuChip Jul 24 '16 at 21:48
  • no, they need not to be consecutive. – saurabh Jul 25 '16 at 13:35
  • @saurabh If they are consecutive then it can not solved, It will become NPC problem see https://en.wikipedia.org/wiki/Subset_sum_problem – Atinesh Feb 07 '17 at 18:01

6 Answers6

9

This is actually the classic subset sum problem, which is a well-known NP-complete problem in computer science.

You can find more information about it on wiki or by searching online for articles on the topic.

Mojtaba Khooryani
  • 1,763
  • 1
  • 17
  • 36
1

The following function just prints the nodes except the ones which are canceled out, you can make it push to a new list and return.

void printExCancel( node* head )
{
    node* start = head;
    node* end;

    while ( start )
    {
        bool mod = false;
        int sum = 0;
        end = start;
        while ( end )
        {
            sum += end->data;
            if ( sum == 0 )
            {
                start = end;
                mod = true;
                break;
            }
            end = end->next;
        }
        if ( mod == false ) {
            //push to new list
            printf( "%d\n", start->data );
        }
        //else {
        //    call funtion to delete from start to end
        //}
        start = start->next;
    }
}
0

Assumption: Only consecutive elements when summed to zero can be removed.
Approach Followed:
  1. Push the non-zero elements of the link list to a stack.
  2. On occurrence of a non zero element:
         (a) Iterate stack, pop each element and keep adding to the non-zero element.
         (b) Keep adding the pop element to a list.
         (c) If the value is zero (that means then by now you have removed ) break stack iteration.
         (d) If stack is Empty & the sum != 0 add the list elements to stack along with the non-zero one

Try Following Code:

    public class ElementSumNonZero {

    private static Node head;

    private static class Node {
        int data;
        Node next;

        Node(int d) {
            data = d;
            next = null;
        }
    }

    private void removeNonZeroElements(Node root) {
     Node start = root;
     Stack<Node> stack = new Stack<>();
     boolean flag = false;
     List<Node> list = new ArrayList<>();
     while (start != null) {
        if (start.data > 0)
            stack.push(start);
        else {
            int sum = start.data;
            flag = false;
            while (!stack.isEmpty()) {
                Node temp = stack.pop();
                sum += temp.data;
                if (sum == 0) {
                    flag = true;
                    list.clear();
                    break;
                }
                list.add(temp);
            }
            if (!flag) {
                list.forEach(i -> stack.add(i));
                stack.add(start);
            }
        }
        start = start.next;
     }
     stack.forEach(i -> System.out.print(i.data +" -> "));
     System.out.println("NULL");
   }

    // Driver program to test above functions
    public static void main(String[] args) {
        ElementSumNonZero list = new ElementSumNonZero();
        ElementSumNonZero.head = new Node(6);
        ElementSumNonZero.head.next = new Node(-6);
        ElementSumNonZero.head.next.next = new Node(8);
        ElementSumNonZero.head.next.next.next = new Node(4);
        ElementSumNonZero.head.next.next.next.next = new Node(-12);
        ElementSumNonZero.head.next.next.next.next.next = new Node(9);
        ElementSumNonZero.head.next.next.next.next.next.next = new Node(8);
        ElementSumNonZero.head.next.next.next.next.next.next.next = new Node(-8);

        list.removeNonZeroElements(head);
    }
}

Test 0
original: {6, -6,6, 8, 4, -12, 9, 8, -8}
canceled out: {9}

Test 1
original: {4, 6, -10, 8, 9, 10, -19, 10, -18, 20, 25}
canceled out: {20, 25}

We can create the resultant stack into a link list and return from "removeNonZeroElements" method.
Please correct me and suggest ways we can make this code efficient.

0

Following python code also passes both the testcases:

class Node():
  def __init__(self,data):
     self.data = data
     self.next = None

class Linkedlist():
   def __init__(self):
     self.head = None
    
   def append(self,data):
     new_node = Node(data)
     h = self.head
     if self.head is None:
         self.head = new_node
         return
     else:
         while h.next!=None:
             h = h.next
         h.next = new_node

   def remove_zeros_from_linkedlist(self, head):
     stack = []
     curr = head
     list = []
     while (curr):
         if curr.data >= 0:
             stack.append(curr)
         else:
             temp = curr
             sum = temp.data
             flag = False
             while (len(stack) != 0):
                 temp2 = stack.pop()
                 sum += temp2.data
                 if sum == 0:
                     flag = True
                     list = []
                     break
                 elif sum > 0:
                     list.append(temp2)
             if not flag:
                 if len(list) > 0:
                     for i in range(len(list)):
                         stack.append(list.pop())
                 stack.append(temp)
         curr = curr.next
     return [i.data for i in stack]

if __name__ == "__main__":
 l = Linkedlist()

 l.append(4)
 l.append(6)
 l.append(-10)
 l.append(8)
 l.append(9)
 l.append(10)
 l.append(-19)
 l.append(10)
 l.append(-18)
 l.append(20)
 l.append(25)
 print(l.remove_zeros_from_linkedlist(l.head))
Community
  • 1
  • 1
kuldeep
  • 1
  • 1
  • Please put your answer always in context instead of just pasting code. See [here](https://stackoverflow.com/help/how-to-answer) for more details. – gehbiszumeis Jan 14 '20 at 09:11
0
'''Delete the elements in an linked list whose sum is equal to zero
E.g-->> 6 -6 8 4 -12 9 8 -8
the above example lists which gets canceled :
6 -6
8 4 -12
8 -8
o/p : 9
case 3 : 4 6 -10 8 9 10 -19 10 -18 20 25
O/P : 20 25'''

#v_list=[6 ,-6, 8, 4, -12, 9, 8, -8]
#Building Nodes
class Node():
    def __init__(self,value):
        self.value=value
        self.nextnode=None
#Class Linked List for Pointing Head and Tail
class LinkedList():
    def __init__(self):
        self.head=None
    
    def add_element(self,value):
        node=Node(value)
        if self.head is None:
            self.head=node
            return
        crnt_node=self.head
        while True:
            if crnt_node.nextnode is None:
                crnt_node.nextnode=node
                break
            crnt_node=crnt_node.nextnode

    def print_llist(self):
        crnt_node=self.head     
        v_llist=[]
        while True:
            print(crnt_node.value,end='->')
            v_llist.append(crnt_node.value) # storing data into list
            if crnt_node.nextnode is None:              
                break
            crnt_node=crnt_node.nextnode
        print('None')
        return v_llist
        
    def print_modified_llist(self):
        p_add=0
        v_llist=self.print_llist()
        #going till the second last element of list and then trying to print requested o/p
        for i in range(len(v_llist)-1):
            p_add=p_add+v_llist[i]
        if v_llist[-1]>0 and p_add>0:
            print(p_add,v_llist[-1])
        elif v_llist[-1]<0 and p_add>0:
            print(p_add+v_list[-1])
        elif v_llist[-1]<0 and p_add<0:
            print(v_llist[-1],p_add)
            

sll=LinkedList()
sll.add_element(4)
sll.print_llist()
sll.add_element(6)
sll.print_llist()
sll.add_element(-10)
sll.print_llist()
sll.add_element(8)
sll.print_llist()
sll.add_element(9)
sll.print_llist()
sll.add_element(10)
sll.print_llist()
sll.add_element(-19)
sll.print_llist()
sll.add_element(10)
sll.print_llist()
sll.add_element(-18)
sll.print_llist()
sll.add_element(20)
sll.print_llist()
sll.add_element(25)
sll.print_llist()
sll.print_modified_llist()
0

Remove elements with consecutive sum = K.

In your case K = 0

  • Append Node with value zero at the starting of the linked list.

  • Traverse the given linked list.

  • During traversal store the sum of the node value till that node with the reference of the current node in an unordered_map.

  • If there is Node with value (sum – K) present in the unordered_map then delete all the nodes from the node corresponding to value (sum – K) stored in map to the current node and update the sum as (sum – K).

  • If there is no Node with value (sum – K) present in the unordered_map, then stored the current sum with node in the map.