pythonpython-3.xdictionarysetdefaultdict

Why is this code taking longer time than expected?


Question: Given a list of unsorted elements, we have to find the length of longest consecutive elements sequence.

Expected time complexity: O(N)

for Ex: [4,7,1,100,28,2,3]

output: 4 since the longest consecutive elements sequence is [1,2,3,4] from the above list

View Problem Statement

I've written the code in Python. I've used set and map (defaultdict) to solve this problem.

from collections import defaultdict as maps
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        nums = set(nums); # to remove duplicates
        n = len(nums);
        if n == 0: return 0;
        if n == 1: return 1;
        present = maps(int);
        # Inserting values into map (defaultdict) as key
        for i in nums:
            present[i] = 1; # to check for presence of element
        i = 0; curr = 0; cnt, maxx = 0, 0; visset = {i for i in nums}
        while n > 0:
              #I had to use this while loop since the for-loop below will get interrupted if we make any changes to the iterating set.
            
            cnt = 1;
            for ind in visset:
                curr = ind; n -= 1; 
                visset.remove(ind); break; #remove is O(1) complexity for set
            # values less than curr::
            curr, temp = curr, curr;
            while n > 0:
                if present[curr - 1]:
                    curr -= 1; n -= 1; 
                    visset.remove(curr); cnt += 1; #remove is O(1) complexity for set
                else:
                    break;
            # values greater than curr::
            while n > 0:
                if present[temp + 1]:
                    temp += 1; n -= 1; 
                    visset.remove(temp); cnt += 1; #remove is O(1) complexity for set
                else:
                    break;
            maxx = max(cnt, maxx);
        maxx = max(cnt, maxx);
        return maxx

for more reference and runtime

Can anybody explain why this code's runtime is higher than intended ?

UPDATE: the runtime of this program is around 7000ms and if I replace set with a dictionary and use del dictt[i] instead of remove() in case of set, the runtime comes down to 2000ms


Solution

  • Yours passes unmodified on leetcode, but it was on the slower end. Here's a simplification of the same code that does a little better than average:

    class Solution:
        def longestConsecutive(self, nums: List[int]) -> int:
            present = set(nums)
            curr = 0
            cnt, maxx = 0, 0
            while present:
                cnt = 1
                start = curr = present.pop()
                while start - 1 in present:
                    start -= 1
                    cnt += 1
                    present.remove(start)
                while curr + 1 in present:
                    curr += 1
                    cnt += 1
                    present.remove(curr)
                maxx = max(cnt, maxx)
            return maxx
    

    You did have a lot of unnecessary data structures, and dumplicate maps where the value wasn't even used. I replaced them all with one set.