techiehub.in

The Art of Array Concatenation: From One-Liners to High Performance

In modern JavaScript, there are often several ways to achieve the same result. A common LeetCode problem, Concatenation of Array, asks us to take an array nums and return a new array that is twice as long, consisting of nums followed by nums.

While the task is simple, the way we solve it reveals a lot about our priorities as developers: Readability vs. Performance.

The Problem

Input: nums = [1, 2, 1]

Output: [1, 2, 1, 1, 2, 1]


Level 1: The Modern One-Liner (Spread Operator)

If you’re working on a standard React app or a small utility function, readability is king. The spread operator (…) is the most idiomatic way to handle this in ES6+.

function getConcatenation(nums) {
    return [...nums, ...nums];
};

Why use it?

  • Declarative: It describes what you want to do, not how to do it.
  • Concise: A single line of code that is instantly understandable by any modern JS developer.

Level 2: The Built-in Specialist (concat)

Before the spread operator, we had Array.prototype.concat. While it looks similar to the spread approach, it is a specialized method designed specifically for joining arrays.

function getConcatenation(nums) {
    return nums.concat(nums);
};

Why use it?

  • Performance: In many JavaScript engines (like V8), concat is highly optimized at the C++ level. It often outperforms the spread operator because it doesn’t have to deal with the overhead of the “iterator protocol” that the spread operator uses.

Level 3: The High-Performance Approach (Manual Pre-allocation)

When you are dealing with massive datasets or competing for the top spot on the LeetCode leaderboard, you need to minimize memory re-allocation.

In the previous two methods, the JavaScript engine starts with a small array and “grows” it as it adds elements. Every time the array grows past its capacity, the engine has to find a new, larger spot in memory and copy everything over.

By pre-allocating the array size, we avoid this overhead entirely.

function getConcatenation(nums) {
    const n = nums.length;

    // We tell the engine EXACTLY how much memory we need upfront
    const ans = new Array(2 * n);

    for (let i = 0; i < n; i++) {
        ans[i] = nums[i];        // Assign to the first half
        ans[i + n] = nums[i];    // Assign to the second half
    }

    return ans;
};

Why use it?

  • Speed: This is the fastest method because it uses direct index assignment.
  • Memory Efficiency: It prevents “Garbage Collection” spikes caused by creating intermediate temporary arrays during the growth phase.

Summary: Which one should you choose?

MethodComplexityUse Case
Spread […]$O(n)$Everyday web development & small arrays.
concat()$O(n)$Clean code that needs a bit more speed.
Pre-allocation$O(n)$High-performance apps, Data Science, or LeetCode.

Categories