Last Updated: June 7, 2026
The task asks for two runs joined together. First count up, 1, 2, ..., n, then count back down, n, ..., 2, 1. For n = 3 that produces [1, 2, 3, 3, 2, 1], where the value n appears twice in the middle, once as the end of the ascending run and once as the start of the descending run.
The exercise turns on the timing of work inside a recursive call. Work written before the call happens on the way down, while the argument is still increasing. Work written after the call happens on the way back up, as the calls unwind in reverse. Recording the current value in both places produces the ascending run and then the descending run from one function.
n is at least 1, so both runs always contain at least one element. The smallest case, n = 1, returns [1, 1].n, so it always terminates.2 x n.A helper function carries the current value i, starting at 1. Before it recurses, it records i, then calls itself with i + 1. After that call returns, it records i again. The first record builds the ascending half because values increase as the calls go deeper. The second builds the descending half because the calls return in reverse order, from the deepest value back to 1.
The base case is reaching a value greater than n. The function returns without recording anything, which is the turning point where the ascending run ends and the descending run begins.
i.i is greater than n, return without recording. This is the base case.i (the ascending half), then call the helper with i + 1.i again (the descending half).1 and return the filled list.Input:
The helper starts at i = 1. It records 1, then calls i = 2, which records 2 and calls i = 3, which records 3 and calls i = 4. Since 4 is greater than n, that call returns at once without recording. The list so far is [1, 2, 3], the ascending run. Now the calls unwind. Back in i = 3, the line after the recursive call records 3, giving [1, 2, 3, 3]. Back in i = 2, it records 2, giving [1, 2, 3, 3, 2]. Back in i = 1, it records 1, giving [1, 2, 3, 3, 2, 1]. The values before the call built the climb, and the values after the call built the descent.
1 to n, and each call records two values in constant time.2 x n values, and the call stack holds up to n pending frames at its deepest point.Without recursion, the two runs are just two loops. The first loop counts up from 1 to n and appends each value. The second loop counts down from n to 1 and appends each value. Joining them gives the same array. This makes the two halves explicit instead of relying on the order in which recursive calls execute and unwind.
i from 1 up to n, append i. This is the ascending run.i from n down to 1, append i. This is the descending run.Input:
The first loop appends 1, 2, and 3, leaving the list as [1, 2, 3]. The second loop appends 3, 2, and 1, extending it to [1, 2, 3, 3, 2, 1]. The result is identical to the recursive version, with the up-loop matching the work done before the recursive call and the down-loop matching the work done after it.
2 x n times, doing constant work per step.2 x n values, with no recursion to grow the stack.