LeetCode – Longest Consecutive Sequence (Java)

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example, given [100, 4, 200, 1, 3, 2], the longest consecutive elements sequence should be [1, 2, 3, 4]. Its length is 4.

Your algorithm should run in O(n) complexity.

Java Solution 1

Because it requires O(n) complexity, we can not solve the problem by sorting the array first. Sorting takes at least O(nlogn) time.

We can use a HashSet to add and remove elements. The add, remove and contains methods have constant time complexity O(1).

public int longestConsecutive(int[] nums) {
    HashSet<Integer> set = new HashSet<>();
    for(int num: nums) set.add(num);
 
    int result = 0;
 
    for(int num: nums){
        int count = 1;
 
        int down = num-1;
        while(set.contains(down)){
            set.remove(down);
            down--;
            count++;
        }
 
        int up = num+1;
        while(set.contains(up)){
            set.remove(up);
            up++;
            count++;
        }
 
        result = Math.max(result, count);
    }
 
    return result;
}

Java Solution 2

We can also project the arrays to a new array with length to be the largest element in the array. Then iterate over the array and get the longest consecutive sequence. If the largest number is very large, then the time complexity would be bad.

47 thoughts on “LeetCode – Longest Consecutive Sequence (Java)”

  1. could we just put all into hash, and for each element check if NOT exist (-1) so, it is start of new consec seq
    and check all next elements: +1 +2 …?

    and on.

    seems like it is o(N), each element accessed only once

  2. To anyone wondering:

    What the provided solution does, is for every number in the input array, it starts stepping downwards, looking for the element that is smaller by one, if it finds one, it keeps going and counts the possible steps, if it doesn’t find the next step it goes back and starts stepping upwards from the initial number, and keeps going one by one, counting the steps, until it reaches a number that is not in the array.
    As a result we get the number of possible steps from the number downwards + the number of possible steps upwards.
    Then it compares that counted result with the result we had so far (with previous elements as starting points), and will return with the largest result.

  3. the condition is set.contains(left), unless it is an infinite set containing all numbers below the initial left value, it won’t be an infinite loop

  4. i would suggest simpler solution
    based on hash

    4 6 8 5 11 15 21 7

    idea:

    #1 add 4 6 8

    4;1 6;1 8;1

    #2 as soon new number and exist number-1, and number +1, add new number and update counters, counting both adjunst (if any)

    lets say new 5 , so update 4;3, ,6;3 and add 5;3

    #3 add 11;1 15;1 21;1

    #4 add 7 , exist 6;3, 8;1 , so update
    6;5, 8;5 and add 7;5

    end!!!!!!

    after than just go over hash elements, find smallest w/ biggest number,,,

    good luck!!!!!!

  5. I’m not familiar with java, I didn’t understand the part:
    while (set.contains(left)) { …; left–; }
    how can we warranty that this is not an infinite loop? because, we can just decrease left– almost infinitely (until 2^-31)

  6. Ok This is my solution
    JavaScritp, ES6, TypeScript

    ```ts

    // time complex O(n)
    // space complex O(n)
    function longestConsIntegers1(data: Array): Array {
    let result = [0,0];
    const map = new Map();

    for(let i = 0; i < data.length; i++) {
    if(data[i] - 1 === data[i-1]) {
    if(!map.has(data[i-1])) {
    map.set(data[i-1],1);
    }
    map.set(data[i], map.get(data[i-1]) +1);
    if(result[1] < map.get(data[i])) {
    result = [i, map.get(data[i])];
    }
    }
    }
    return data.splice(result[0] - result[1] + 1, result[1]);
    }

    let arr = [10,9,8,11,12,13,14,31,32];
    longestConsIntegers1(arr)
    ```

  7. Transformo el vector int [ ] ——> List a una lista de enteros


    public static void method(List ListaDato)
    {
    List mayorConsecutivos = new ArrayList(ListaDato.get(0));

    for(int i=0; i<ListaDato.size(); i++)
    {
    int aux = ListaDato.get(i);
    List consecutivos = new ArrayList();
    consecutivos.add(aux);

    while (tieneSiguiente(ListaDato, aux))
    {
    consecutivos.add(aux+1);
    aux +=1;
    }

    if(consecutivos.size()>mayorConsecutivos.size())
    {
    mayorConsecutivos = consecutivos;
    }
    }

    for (int m : mayorConsecutivos)
    {
    System.out.print(m);
    }

    }


    public static boolean tieneSiguiente(List ListaDato, int num)
    {
    int siguiente = num+1;
    for(int i=0; i<ListaDato.size();i++)
    {
    if (ListaDato.get(i) == siguiente)
    {
    return true;
    }
    }
    return false;
    }

  8. IMHO the code above works fine.
    The linear complexity thought (although asymptotically linear) is not optimal IMO.
    The number of lookups can be reduced, using disjoint set (see solution above).

  9. The proposed solution is correct, but I’m not sure it’s optimal performance-wise.
    I have used disjoint sets, so the interval coalescing is done almost in constant time.

    from disjoint_set import make_set, find_set, union

    class Interval:
    def __init__(self, l, r):
    self.l = l
    self.r = r

    def __len__(self):
    return self.r - self.l + 1

    def __str__(self):
    return '({0}, {1})'.format(self.l, self.r)

    def _unify(lint, rint):
    if lint.l < rint.l:
    the_interval = Interval(lint.l, rint.r)
    else:
    the_interval = Interval(rint.l, lint.r)
    return (the_interval, the_interval)

    def max_interval(l, r):
    if l == r:
    return l
    dlen = len(l.item) - len(r.item)
    return r if dlen < 0 else l

    def longest_seq(arr):
    s = {}
    for num in arr:
    s[num] = make_set(Interval(num, num))
    ldset = dset = rdset = None
    if num-1 in s:
    ldset = s[num-1]
    dset = s[num]
    if num+1 in s:
    rdset = s[num+1]
    if ldset:
    union(ldset, dset, _unify)
    if rdset:
    union(rdset, dset, _unify)
    max_dset = None
    for (_, dset) in s.items():
    rep = find_set(dset)
    if max_dset is None:
    max_dset = rep
    continue
    if max_dset == rep:
    continue
    max_dset = max_interval(rep, max_dset)
    return max_dset

    if __name__ == '__main__':
    arr = map(int, raw_input().split())
    print(longest_seq(arr).item)

  10. worked for me. Also its not necessary to delete the element e cause you are deleting all the left and rights related to that particular center. so it will never be counted again.

  11. Curious.. can we use priority queue to add the elements in sorted orde, the offer complexity is o(log n) and then check if its consecutive which will just be o(n).
    Anyone tell me why this isnt o(n)?

  12. For input {8,7,6,5,4,3,2,1}, the first loop time is 8, the second is 1 because [7..1] are removed, same for the left iterations.

  13. for input {8,7,6,5,4,3,2,1} the complexity of this solution will be O(n^2). The second for loop, when run with e=8 will remove all the elements from the set. Thus, for e=8, the while loop that runs, will be of O(n) and after that, the for loop will still iterator for other 7 values (though each time it will return false for set.contains(left)) but still the for loop will run n times nonetheless. The worst case complexity of this solution is thus O(n^2) and not O(n).

  14. Is this comment about an old implementation? in the given example m = 1 (not n). And, following the code, what would happen would be that each “set.contains” would return false, and the whole array will be iterated once more => the complexity would be O(N). What am I missing?

  15. TreeSet is a balanced search tree (guarantees log N cost operations). Thus, the total insertion cost is N log N (required time complexity is O(N)


  16. //Longest Consecutive Sequence (Java)
    // Note: this is longest "consecutive" elements sequence, i.e., 1,2,3,4 is correct since difference
    // between neighbors is 1, e.g. 4-3=1, 3-2=1, and so
    public int solution(int[] arr){
    Set tree = new TreeSet();
    for (int a : arr) {
    tree.add(a);
    }
    Integer[] newarr = new Integer[myarr.length];
    tree.toArray(newarr);
    int ans = 1;
    int max = ans;
    for (int i = 1; i ans) {
    ans = max;
    }
    }
    return ans;
    }

  17. I had the same idea. But for huge number as max and min the running time would be terrible. Imagine [-10ˆ1000000000000000, 10ˆ1000000000000000]. Only two numbers on list and you would take a bunch of time. So it would be O(max-min). It would, but hash seem be better in this case

  18. the valid subsequences will [100,200], [4,200], [1,3], [1,2]
    All these are valid longest increasing sub sequence. But the answer can’t be 4.

  19. I don’t think this was the actual question.

    If you see the example given in leetcode,

    [10, 9, 2, 5, 3, 7, 101, 18],

    for this it takes the longest subsequence as [2, 5, 7, 101]

    It doesn’t take into account the higher numbers which came previously.

    Have you tried running the code in leetcode?

    the example you have given, [100, 4, 200, 1, 3, 2]

    when run in leetcode, gives the answer as 2 i.e., 100 and 200
    whereas you say the answer is 4.

  20. why not remove(num) after each checking? It will not affect the result anyway. Then for the extreme case you will also get O(N).

  21. why dont you iterate throw the set, rather than the array? It will avoid checking for the duplicate values in array.

  22. Adding “if(!set.contains(e)) continue” after the second “for” line appears to make it completely O(n).

  23. If ‘set.contains(…)’ is O(1) then whole solution can be considered as O(n).
    Another solution without using of Hash is do sorting first, the average complexity will be O(NlogN), plus an O(n) to find out longest sequence.

  24. for (int e : num)
    set.add(e);

    Above code will use O(N) time right? where N is number of elements in array num. Yes add operation takes constant time O(1) to add an element in a hash set with perfect hash function, but if we repeat an operation of O(1) in a loop for N times it will have time complexity of O(N) as it time taken will grow/shrink with value of N. Am i understanding it correctly?

  25. What do you mean by n == m? It doesn’t seem to me to be possible unless the whole set contains a whole consecutive sequence, in which case the runtime is still O(n). The example{1,3,5,7,9} in the article doesn’t seem to satisfy this condition?

  26. In the first for loop I can get the min and max number of the array, beside put them in hash. Then I can loop through from min through max to see where longest consecutive sequence is. I think this way would be clear. If the number is very scattered, the complexity can not be much bigger than O(n).

Leave a Comment