Concatenation of Array
Build an array of length 2n by concatenating the input array with itself.
O(n)O(n)Given an array of n integers nums, create an array ans of length 2n such that:
ans[i] == nums[i]
ans[i + n] == nums[i] # for 0 <= i < nIn other words, return nums concatenated with itself.
Constraints
- Input: one line of space-separated integers (read from stdin with
split_whitespace()). - Output: print 2n space-separated integers on one line.
- Length:
1 <= n <= 1000(LeetCode bounds);n = 0is not in scope. - Values: integers in the input (positives, zeros, and negatives are all valid).
Input
1 2 3 4
Output
1 2 3 4 1 2 3 4
Explanation: Standard case — the input is appended to itself once.
Walk through numbers twice, appending each element to a new list one at a time.
This is correct and easy to reason about, but performs 2n separate append operations and may trigger multiple buffer reallocations as the result grows.
// Walk numbers twice, pushing each element onto a new Vec.
// Time: O(n) Space: O(n)
fn concatenate_arrays_naive(numbers: &[i64]) -> Vec<i64> {
let mut result: Vec<i64> = Vec::new();
for _ in 0..2 {
for &number in numbers {
result.push(number);
}
}
result
}Time — O(n)
Each of the 2n elements is copied once → O(n).
Space — O(n)
The result array holds 2n integers. Repeated appends may cause intermediate reallocations.
Time: two full passes over the input — acceptable, but each pass is a separate loop.
Space: growing the result with push/append may reallocate the backing buffer more than once.
Next step: pre-allocate a 2n buffer and copy each half in one or two bulk writes.
Pre-allocate a buffer of length 2n, then:
- Pass 1 — copy
numbersinto indices[0, n). - Pass 2 — copy
numbersinto indices[n, 2n).
Bulk slice copies avoid per-element appends.
// Allocate a 2n Vec and copy numbers into both halves:
// positions [0, n) and positions [n, 2n) each receive the full slice.
// Time: O(n) Space: O(n)
fn concatenate_arrays(numbers: &[i64]) -> Vec<i64> {
let numbers_length: usize = numbers.len();
let mut concatenated_array: Vec<i64> = vec![0; 2 * numbers_length];
concatenated_array[..numbers_length].copy_from_slice(numbers);
concatenated_array[numbers_length..].copy_from_slice(numbers);
concatenated_array
}Time — O(n)
Two linear copies of n elements each → O(n).
Space — O(n)
One pre-allocated buffer of size 2n — no reallocations.
Single pass: for each index i from 0 to n − 1, write numbers[i] to both result[i] and result[i + n] in the same iteration.
One loop fills the entire output — no second scan over the input.
// Single pass: at each index i, write numbers[i] to both halves.
// Time: O(n) Space: O(n)
fn concatenate_arrays_optimal(numbers: &[i64]) -> Vec<i64> {
let numbers_length: usize = numbers.len();
let mut concatenated_array: Vec<i64> = vec![0; 2 * numbers_length];
for idx in 0..numbers_length {
concatenated_array[idx] = numbers[idx];
concatenated_array[idx + numbers_length] = numbers[idx];
}
concatenated_array
}Time — O(n)
One pass, two writes per iteration → O(n).
Space — O(n)
Pre-allocated buffer of size 2n.