You are given an integer array nums
representing a stack, where nums[0]
is the topmost element. You are also given an integer k
representing the maximum number of moves you can make. In each move, you can either:
You must make exactly k
moves. After k
moves, if the stack is not empty, you want to maximize the value of the topmost element. If the stack is empty after k
moves, return -1
.
Constraints:
k
moves.k
moves, or return -1
if impossible.
At first glance, it seems you could try all possible sequences of removes and puts, but this approach quickly becomes infeasible for large k
or large stacks. Instead, we look for patterns and constraints:
k
equals the stack size.k
elements of the stack (since you can't remove more than k
elements in k
moves).k
moves, so we need to consider which element can be placed on top after exactly k
moves.
The key insight is to recognize that you can only ever put back elements you've removed, and you can't put back more than one per move. The number of elements you can remove is at most k
. The optimal strategy is to consider the largest possible element among the first k-1
elements (since you can remove and put back any of them), and possibly the k
-th element if you just keep removing.
Let's break the solution into clear steps:
k == 0
, you can't do anything, so the answer is just nums[0]
.
k == 1
, you can only remove the top element or leave it. If the stack has only one element, removing it leaves the stack empty, so return -1. Otherwise, after one move, the top is nums[1]
.
k
is less than the length of nums
:
k-1
elements and put back any one of them as the top, or just remove k
elements and leave the k
-th element as the new top.
k
moves are:
k-1
elements (if you remove and put back one of them), ork
-th element (nums[k]
) if you just keep removing.k
is greater than or equal to the length of nums
:
nums
.
n == 1
and k
is odd, you will end up with an empty stack, so return -1.
Implementation Tips:
k-1
elements.k
is close to the length of nums
.
Let's consider nums = [2, 4, 1, 5, 3]
and k = 3
:
k-1 = 2
elements and put back any one of them as the top, or just remove 3 elements and have nums[3] = 5
as the new top.
k-1 = 2
elements are 2
and 4
. The maximum is 4
.
nums[3]
) is 5
.
max(4, 5) = 5
.
If nums = [1]
and k = 1
:
-1
.Brute-force Approach:
O(2^k)
.
k-1
elements, and possibly compare with nums[k]
(if k < n
), so the time complexity is O(k)
.
O(1)
, since we only store a few variables for tracking the maximum.
The key to solving this problem efficiently is recognizing that you can only ever put back elements you've removed, and you can't do more than one operation per move. By focusing on the first k-1
elements and considering the k
-th element, we avoid brute-force and quickly compute the answer. This approach is both elegant and efficient, leveraging careful analysis of the stack operations and move constraints.
class Solution:
def maximizeTopmostElement(self, nums: List[int], k: int) -> int:
n = len(nums)
if k == 0:
return nums[0] if n > 0 else -1
if n == 1:
# If k is odd, stack is empty, else the only element remains
return -1 if k % 2 == 1 else nums[0]
if k == 1:
return nums[1] if n > 1 else -1
if k >= n:
return max(nums)
# Consider the max among the first k-1 elements and nums[k]
max_in_prefix = max(nums[:k-1])
# Optionally, nums[k] can be the new top if we just keep removing
if k < n:
return max(max_in_prefix, nums[k])
else:
return max_in_prefix
class Solution {
public:
int maximizeTopmostElement(vector<int>& nums, int k) {
int n = nums.size();
if (k == 0) return n > 0 ? nums[0] : -1;
if (n == 1) return (k % 2 == 1) ? -1 : nums[0];
if (k == 1) return n > 1 ? nums[1] : -1;
if (k >= n) {
int mx = nums[0];
for (int i = 1; i < n; ++i) mx = max(mx, nums[i]);
return mx;
}
int mx = nums[0];
for (int i = 1; i < k - 1; ++i) mx = max(mx, nums[i]);
return max(mx, nums[k]);
}
};
class Solution {
public int maximizeTopmostElement(int[] nums, int k) {
int n = nums.length;
if (k == 0) return n > 0 ? nums[0] : -1;
if (n == 1) return (k % 2 == 1) ? -1 : nums[0];
if (k == 1) return n > 1 ? nums[1] : -1;
if (k >= n) {
int mx = nums[0];
for (int i = 1; i < n; ++i) mx = Math.max(mx, nums[i]);
return mx;
}
int mx = nums[0];
for (int i = 1; i < k - 1; ++i) mx = Math.max(mx, nums[i]);
return Math.max(mx, nums[k]);
}
}
var maximizeTopmostElement = function(nums, k) {
let n = nums.length;
if (k === 0) return n > 0 ? nums[0] : -1;
if (n === 1) return (k % 2 === 1) ? -1 : nums[0];
if (k === 1) return n > 1 ? nums[1] : -1;
if (k >= n) {
return Math.max(...nums);
}
let mx = nums[0];
for (let i = 1; i < k - 1; ++i) {
mx = Math.max(mx, nums[i]);
}
return Math.max(mx, nums[k]);
};