I'm testing it with 1,000,000 numbers, and it's just kind of hanging. I thought it would breeze through 1,000,000 easily. Is it my implementation? I have a feeling it's because of the slice()
, anyone have an idea?
Edit:
Just got this message:
FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory
TopDownSplitMerge(numbersArray);
function TopDownSplitMerge(arrayOfNumbers) {
var length = arrayOfNumbers.length
var middleIndex = parseInt(length/2);
if(length <= 1) {
return arrayOfNumbers;
}
// Split left side
var left = TopDownSplitMerge(arrayOfNumbers.slice(0, middleIndex));
// Split right side
var right = TopDownSplitMerge(arrayOfNumbers.slice(middleIndex, length));
// Merge every back together
return TopDownMerge(left, right);
}
function TopDownMerge(left, right) {
var results = []
while(left.length || right.length) {
console.log("looping...");
// Check if both sides are NOT empty, if so, then just finish shifting the non-empty side
if(left.length && right.length) {
if(left[0] <= right[0]) {
results.push(left.shift())
} else {
results.push(right.shift())
}
} else if(left.length) {
results.push(left.shift())
} else {
results.push(right.shift())
}
}
console.log("Merging....", results.length);
return results;
}
There are two things I had to change
var right = TopDownSplitMerge(arrayOfNumbers.slice(middleIndex, length));
....
....
....
function TopDownMerge(left, right) {
var results = [], leftLen = left.length, rightLen = right.length;
for (var i = 0, j = 0; i < leftLen || j < rightLen;) {
if (i < leftLen && j < rightLen) {
if(left[i] <= right[j]) {
results.push(left[i]);
i += 1;
} else {
results.push(right[j]);
j += 1;
}
} else if (i < leftLen) {
results.push(left[i]);
i += 1;
} else {
results.push(right[j]);
j += 1;
}
}
return results;
}
Edit: Now I changed it to accept indices instead of sliced arrays and it boosts the performance more.
function TopDownSplitMerge(arrayOfNumbers, start, end) {
var length = end - start;
var middleIndex = start + parseInt(length / 2);
if (length <= 1) {
return [arrayOfNumbers[start]];
}
// Split left side
var left = TopDownSplitMerge(arrayOfNumbers, start, middleIndex);
// Split right side
var right = TopDownSplitMerge(arrayOfNumbers, middleIndex, length);
// Merge every back together
return TopDownMerge(left, right);
}
TopDownSplitMerge(numbersArray, 0, numbersArray.length);
Jsperf: http://jsperf.com/so-q-19341534
jsperf for my solution with 10,000,000 numbers: http://jsperf.com/solution-to-so-q-19341534