dailycodingproblem.com: longest consecutive sequence
intro⌗
Let’s start off today’s article with a couple of definitions:
- sequence: commonly defined as a list containing elements that follow each other in order. Such as
[1, 2, 3, 4]
- O(n): a generic measurement of time that says that the operation will take as big as N is. So, if the value is 5, the operation will take 5 units of time.
- unsorted array: the opposite of a sorted array, instead of
[1, 2, 3, 4]
, you’d have[4, 2, 1, 3]
Okay, let’s back to the main issue at hand. Instead of going about this solution with wanting to accomplish O(n)
, I’d rather go after the inefficient solution and then work our way towards the golden O(n)
inefficient solution⌗
Well, if you have an unsorted array, why don’t you sort it first, then deal with it later. In the language I am using which is Javascript
, you could easily sort through an array of integers through the function sort()
.
[1, 5, 2, 0, 4].sort()
// [0, 1, 2, 4, 5]
Afterwards, you can loop over the items twice, get the local longest consecutive sequence, compare it to the global longest consecutive sequence and you’re done.
function solve(arr) {
arr = arr.sort();
var max = 1;
// first loop
for(let i=0; i < arr.length; i++) {
var last = arr[i]
var loopMax = 1;
for(let j=i+1; j < arr.length; j++) {
if(last == arr[j]-1) {
last = arr[j];
loopMax++;
if(loopMax > max) {
max = loopMax;
}
} else {
break;
}
}
last = arr[i]
}
return max;
}
efficient solution: trade time for space⌗
While the inefficient solution uses at most 3 or 4 extra variables, this solution uses O(n*2) of space but, more importantly, O(n) of time.
Here are the steps to accomplish the solution:
- do not sort the array
- create a map to store consecutive sequence number for each number
- check the number behind each two numbers, i.e if x = 2, check for 1 and 3’s values in the map
- if they exist: search for the previous and next numbers in the map, connect them and set them to same value
- if not, create an entry in map equal to 1, since consecutive sequences start at 1
- compare this number’s consecutive sequence to the previous one, and if it’s larger set the previous one to the new one.
Here’s how the code would look:
function solve(arr) {
var m = new Map();
var max = -1;
for(var i in arr) {
var curr = arr[i];
console.log(curr)
var prev = curr - 1
var next = curr + 1;
var obj = null;
if(m.get(prev) !== undefined) {
obj = m.get(prev);
obj.num += 1
}
if(m.get(next) !== undefined) {
if(obj !== null) {
obj.num += m.get(next).num;
m.set(next, obj)
} else {
obj = m.get(next);
obj.num += 1
}
}
if(obj === null) {
obj = {num: 1}
}
m.set(curr, obj);
if(max < obj.num) {
max = obj.num;
}
}
return max
}
The reason this works is that the map keeps track of the consecutive sequence through the use of objects. So, if 3 numbers are in a sequence, modifying one number’s field modifies every single number num field in the sequence.
personal notes⌗
This problem was one of the most fun problems I’ve done in a while, it strkes that perfect balance between hard enough to be challenging but not too hard to be disheartening. I am glad I came up with the solution without seraching it on google.