class Solution:
def buildArray(self, target, n):
res = []
curr = 1
i = 0
while i < len(target):
if curr == target[i]:
res.append("Push")
i += 1
else:
res.append("Push")
res.append("Pop")
curr += 1
return res
class Solution {
public:
vector<string> buildArray(vector<int>& target, int n) {
vector<string> res;
int curr = 1, i = 0;
while (i < target.size()) {
if (curr == target[i]) {
res.push_back("Push");
++i;
} else {
res.push_back("Push");
res.push_back("Pop");
}
++curr;
}
return res;
}
};
class Solution {
public List<String> buildArray(int[] target, int n) {
List<String> res = new ArrayList<>();
int curr = 1, i = 0;
while (i < target.length) {
if (curr == target[i]) {
res.add("Push");
i++;
} else {
res.add("Push");
res.add("Pop");
}
curr++;
}
return res;
}
}
var buildArray = function(target, n) {
let res = [];
let curr = 1, i = 0;
while (i < target.length) {
if (curr === target[i]) {
res.push("Push");
i++;
} else {
res.push("Push");
res.push("Pop");
}
curr++;
}
return res;
};
You are given a strictly increasing array target
containing integers from 1 to n
(inclusive), and an integer n
. You have an empty stack and can perform two operations: Push (add the next number in sequence from 1 to n
onto the stack), and Pop (remove the top element from the stack). Your goal is to build the target
array by simulating these stack operations in order, starting from 1 up to n
(but you may stop early if target
is completed).
For each number from 1 to n
:
target
, you must Push it onto the stack.target
, you must Push it and then immediately Pop it.target
array. Each number from 1 to n
can be used at most once and in order. The solution is unique.
At first glance, you might consider simulating the stack fully, pushing and popping values as needed, or even trying to generate all possible sequences. However, the problem's constraints and the strictly increasing property of target
mean that for each value from 1 to n
, you know exactly what to do:
target
, you Push it and move to the next target value.
This leads to a direct and efficient solution, where you only need to iterate through numbers from 1 up to the last value in target
(since all target
values are between 1 and n
).
Let's break down the solution step by step:
target
array. Start a counter at 1 to represent the next number to consider.
target[-1]
(the largest number in target
):
target
value, append "Push" to the result and move to the next target
value.target
are processed, you can stop. There's no need to continue up to n
.
This approach is both simple and efficient because it leverages the properties of the input: strictly increasing and unique values in target
.
Let's walk through an example with target = [2, 3, 4]
and n = 4
:
target[0] = 2
, so 1 is not in target
.target[0] = 2
, so 2 is in target
.target[1] = 3
, so 3 is in target
.target[2] = 4
, so 4 is in target
.So the output would be: ["Push", "Pop", "Push", "Push", "Push"].
Brute-force approach: If you tried to generate all possible stack operation sequences, the time and space complexity would be exponential, which is infeasible for even moderate values of n
.
Optimized approach (used here):
target
. This is because we only process numbers up to target[-1]
, and at each step we do a constant amount of work.target
(in the case where every non-target element is pushed and popped).
The key insight is to leverage the strictly increasing nature of target
and the requirement to process numbers in order from 1 to n
. By comparing each number with the next target value, we can efficiently decide whether to "Push" or "Push" and "Pop". This direct approach avoids unnecessary simulation and results in a simple, efficient, and elegant solution.