Get Maximum in Generated Array: Simulation Pattern
You are given an integer n. You need to build an array nums of length n + 1 following specific rules, then return the maximum value in it.
This is LeetCode 1646: Get Maximum in Generated Array, and it is a great example of the simulation pattern. The problem gives you a set of rules, and your job is to follow them exactly, step by step. No clever trick is needed. Just careful execution.
Why this problem matters
Simulation problems test whether you can translate a specification into code without overcomplicating things. Many developers trip up by trying to find a mathematical shortcut when the problem is really asking you to just do what it says. That skill, reading a set of rules and implementing them faithfully, is exactly what you do every day as a software engineer.
The pattern here also connects to dynamic programming. Each value in the array depends on previously computed values, which is the core idea behind DP. Practicing simulation builds your intuition for recognizing when you can compute things iteratively from earlier results.
The key insight
The array construction has two rules:
- For even indices:
nums[2 * i] = nums[i] - For odd indices:
nums[2 * i + 1] = nums[i] + nums[i + 1]
Each element depends only on elements that come before it in the array. That means you can fill the array from left to right, and by the time you need a value, it will already be computed. All you have to do is iterate through the rules and track the running maximum.
The solution
def get_maximum_generated(n):
if n == 0:
return 0
nums = [0] * (n + 1)
nums[1] = 1
max_val = 1
for i in range(1, n + 1):
if 2 * i <= n:
nums[2 * i] = nums[i]
max_val = max(max_val, nums[2 * i])
if 2 * i + 1 <= n:
nums[2 * i + 1] = nums[i] + nums[i + 1]
max_val = max(max_val, nums[2 * i + 1])
return max_val
The function starts by handling the n = 0 edge case. Then it creates the array, seeds nums[1] = 1, and iterates from i = 1 up to n. At each step, it applies both rules (if the target index is within bounds) and updates the running maximum. By the time the loop finishes, every index has been filled and the maximum has been tracked.
When a simulation problem gives you index-based rules, always check bounds before writing to an index. The condition 2 * i + 1 can easily exceed n, so guarding against that is essential.
Visual walkthrough
Let's trace through the full construction for n = 7 step by step. Watch how each new cell is computed from values that already exist in the array.
Base cases: nums[0] = 0, nums[1] = 1
The first two values are given directly by the problem.
i=1: nums[2] = nums[1] = 1
Even index rule: nums[2*1] = nums[1] = 1.
i=1: nums[3] = nums[1] + nums[2] = 1 + 1 = 2
Odd index rule: nums[2*1+1] = nums[1] + nums[2] = 2.
i=2: nums[4] = nums[2] = 1
Even index rule: nums[2*2] = nums[2] = 1.
i=2: nums[5] = nums[2] + nums[3] = 1 + 2 = 3
Odd index rule: nums[2*2+1] = nums[2] + nums[3] = 3. New maximum found!
i=3: nums[6] = nums[3] = 2
Even index rule: nums[2*3] = nums[3] = 2.
i=3: nums[7] = nums[3] + nums[4] = 2 + 1 = 3
Odd index rule: nums[2*3+1] = nums[3] + nums[4] = 3. Array complete. Maximum = 3.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Simulation (iterative) | O(n) | O(n) |
You visit each index at most once and perform constant work per index. The array itself takes O(n) space. There is no way to avoid this because the problem explicitly asks you to build the array.
The building blocks
This problem is built on two reusable patterns that show up across many LeetCode problems.
1. Iterative array construction
The core idea is filling an array where each element depends on previously computed elements. You start with base cases and iterate forward, computing new values from old ones.
nums = [0] * (n + 1)
nums[1] = 1
for i in range(1, n + 1):
if 2 * i <= n:
nums[2 * i] = nums[i]
This is the same structure you see in Fibonacci, Pascal's Triangle, and many DP problems. The only difference is the recurrence relation. Once you recognize "each value depends on earlier values," you know you can build it iteratively.
2. Tracking a running maximum
Instead of building the full array and then scanning for the max, you can track the maximum as you go. This keeps the code clean and avoids a second pass.
max_val = 1
for i in range(1, n + 1):
if 2 * i + 1 <= n:
nums[2 * i + 1] = nums[i] + nums[i + 1]
max_val = max(max_val, nums[2 * i + 1])
This running-maximum technique appears everywhere: in Kadane's algorithm, in stock trading problems, and in any problem where you need the best value seen so far.
Edge cases
Before submitting, make sure your solution handles these:
- n = 0: the array is just
[0], so return 0. This is the most common edge case people miss. - n = 1: the array is
[0, 1], return 1. - n = 2: the array is
[0, 1, 1], return 1. The even-index rule copiesnums[1]tonums[2], but the odd-index rule does not fire because2 * 1 + 1 = 3 > 2. - Large n (up to 100): the simulation runs in linear time, so performance is not a concern.
From understanding to recall
You have walked through the construction step by step and the logic makes sense. But the gap between understanding and recall is real. In an interview, you need to produce the bounds checks, the two separate rules, and the edge case handling from memory.
Spaced repetition closes that gap. By revisiting this problem at increasing intervals, you move the simulation pattern from short-term understanding into long-term recall. Each time you rebuild the solution, you reinforce the habit of checking index bounds, tracking a running maximum, and handling n = 0 separately.
The simulation pattern is one of the most common building blocks in easy and medium LeetCode problems. Mastering it through deliberate practice makes dozens of similar problems feel routine.
Related posts
- Climbing Stairs - Another problem where each value depends on previously computed values, using the same iterative construction pattern
- Pascal's Triangle - Building a 2D structure row by row, with each cell derived from earlier cells
- Fibonacci Number - The classic iterative recurrence, and the simplest example of "fill from base cases forward"
CodeBricks organizes problems like this by their underlying building blocks, not by arbitrary difficulty labels. When you learn simulation as a reusable pattern, you stop seeing each new problem as a blank slate and start recognizing the familiar structure underneath.