-3
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head == None:
            return None
        start = head
        prev = head.val
        a = {prev:1}
        #o = [prev]
        head = head.next
        while head != None:
            if head.val == prev:
                a[prev] += 1
            else:
                prev = head.val
                a[prev] = 1
                #o.append(prev)
            head = head.next
        b = ListNode(0)
        ans = b
        for i in a: # can use for i in o
            if a[i] == 1:
                c = ListNode(i)
                b.next = c
                b = b.next
        return ans.next

I am trying to remove duplicate items from a sorted linked list, eg.[1,2,3,3,4,4,5,6,6,6] -> [1,2,5]. Can someone walk through the code and tell me what will be the final value of a is for the linked list 2->1->None. It should be {2:1, 1:1} but answer comes out to be {1:1, 2:1}...why?

Nikhil Ranjan
  • 185
  • 1
  • 6

5 Answers5

2

dict object doesn't remember the order of elements which are added to the dictionary. If you want to preserve the ordering of the elements you can use OrderedDict.

Alireza Mika
  • 71
  • 1
  • 4
1

O(N) option using groupby

>>> from itertools import groupby
>>> [k for k,g in groupby([1,2,3,3,4,4,5,6,6,6]) if len(list(g)) == 1]
[1, 2, 5]
Luka Rahne
  • 10,336
  • 3
  • 34
  • 56
0

Try the following:

>>> l = [1,2,3,3,4,4,5,6,6,6]
>>> [i for i in l if l.count(i) == 1]

This preserves the order of items in l.

a_guest
  • 34,165
  • 12
  • 64
  • 118
0

This answer assumes that all you want to do is to create another list, only keeping the values that occur once.

One way of doing it would be to use groupby from itertools and then filter based on the length of each group.

# Assuming 's' holds our list
[i for i,k in itertools.groupby(s) if len(list(k)) == 1]

EDIT Reading your question again, it seems this solution might not work, unless the linked list type you're using conforms to the iterator protocol. At any rate, it certainly won't produce a list as output, although you could replace the list comprehension with a generator expression and build a linked list from that.

SwiftsNamesake
  • 1,540
  • 2
  • 11
  • 25
0

Here's an approach in O(n) time (in Python 3), regardless of whether the list is sorted.

>>> lst = [1, 2, 3, 3, 4, 4, 5, 6, 6, 6]
>>> unique = {}
>>> for item in lst:
...     if item in unique:
...         unique[item] += 1
...     else:
...         unique[item] = 1
... 
>>> [k for k, v in unique.items() if v == 1]
[1, 2, 5]
  • The statement for item in lst: ... is O(n).
    • The expression item in unique is O(1).
    • The statement unique[item] = 1 is O(1), and so is unique[item] += 1.
  • The expression [k for k, v in unique.items() if v == 1] is O(n).

So, calculating the time complexity of the for statement:

  1. O(n) * (O(1) + max(O(1), O(1)))
  2. O(n) * (O(1) + O(1))
  3. O(n) * O(1)
  4. O(n)

Add that to the time complexity of the list comprehension, and you have O(n) + O(n), which is O(2n). Drop the constant, and you have O(n).

Zach Gates
  • 4,045
  • 1
  • 27
  • 51