Skip to article
ALGORITHMICSDSA / Arrays
DSAeasy6 min read

Concatenation of Array

A three-line problem that is really about Go slices — capacity, copying, and who owns the array.


Given nums of length nn, return an array of length 2n2n that is nums followed by nums again.

[]int{1, 3, 2, 1} // → [1 3 2 1 1 3 2 1]

The algorithm is not the point. Everything interesting here is about how Go slices actually behave, and this is the smallest problem where you can see it.

The solution

func getConcatenation(nums []int) []int {
var size = len(nums)
var ans = make([]int, 2*size)
for i, v := range nums {
ans[i] = v
ans[size+i] = v
}
return ans
}

One pass over nums, two writes per iteration:

1 / 4
nums
▾ i 1 0
3 1
2 2
1 3
ans — allocated once, at length 8
1
·
·
·
1
·
·
·

nums[0] is written to ans[0] and ans[4 + 0] in the same iteration. Both destinations already exist — nothing grows, nothing is copied to make room, and the loop runs exactly 4 times rather than 8.

O(n)O(n) time, O(n)O(n) space — and the space is the output, so there is nothing extra.

Say the length or say the capacity, not neither

Three spellings, and the difference is not stylistic:

ans := make([]int, 2*size) // length 2n, all zero — index into it
ans := make([]int, 0, 2*size) // length 0, capacity 2n — append into it
ans := []int{} // length 0, capacity 0 — append and realloc

copy says it better

The loop is fine. The standard library states the intent in two lines:

func getConcatenation(nums []int) []int {
size := len(nums)
ans := make([]int, 2*size)
copy(ans, nums)
copy(ans[size:], nums)
return ans
}

copy moves as many elements as fit in the shorter of the two slices and returns that count. For a slice of a basic type it compiles down to a bulk memory move rather than an element-at-a-time loop, so it is also faster than the version above — the gap widens with n.

ans[size:] is a view onto the second half of the same array, not a new one. No allocation happens on that line.

The one-liner, and why it is a trap

return append(nums, nums...)

This produces the right answer on LeetCode. It can also corrupt data belonging to the caller.

What it is actually teaching

The concatenation is a pretext. The habits are the point, and they carry to every array problem you will write:

The same three show up in merge sort’s merge step, which allocates its output up front for exactly these reasons.