Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions solution/2400-2499/2454.Next Greater Element IV/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -833,3 +833,112 @@ class TreeMultiSet<T = number> {
<!-- solution:end -->

<!-- problem:end -->


### 方法二:双栈
准备两个单调递减栈

一号栈装 __还未曾碰到过任何一个__ 比自己大的右边元素的所有$nums[i]$

二号栈装 __已经碰到过刚好有一个__ 比自己大的右边元素的所有$nums[j]$

遍历$nums$过程中 当前被轮值到的$nums[k]$先检查二号栈

只要二号栈还有元素 且顶部元素小于$nums[k]$

把顶部元素从二号栈弹出 记录它找到$nums[k]$作为答案

等到二号栈要嘛全空 要嘛顶部元素不小于$nums[k]$

$nums[k]$的工作变成是检查一号栈

同理 只要一号栈还有元素 且顶部元素小于$nums[k]$

顶部元素弹出一号栈 先去```transporter```上待著

等到一号栈要嘛全空 要嘛其顶部元素不小于$nums[k]$

$nums[k]$就结束了任务 能进入一号栈等待未来

刚才说的```transporter```从尾部陆续弹出元素装入二号栈内

时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。

这是由于每个元素最多被压入和弹出两个栈合计四次。

空间复杂度 $O(n)$。

<!-- tabs:start -->

#### Python3

```python
class Solution:
def secondGreaterElement(self, nums: list[int]) -> list[int]:
second_next_greater = [-1] * len(nums)

stack_1: list[tuple[int, int]] = [] # Decreasing monotonic stacks: (num, idx).
stack_2: list[tuple[int, int]] = []

transporter: list[tuple[int, int]] = [] # Transport tuples from stack 1 to stack 2.

for idx, num in enumerate(nums):
while stack_2 and stack_2[-1][0] < num:
_, past_idx = stack_2.pop(-1)
second_next_greater[past_idx] = num

while stack_1 and stack_1[-1][0] < num:
transporter.append(stack_1.pop(-1))

while transporter:
stack_2.append(transporter.pop(-1)) # Ensure decreasing monotonicity.
stack_1.append((num, idx))

return second_next_greater
```

#### C++

```cpp
class Solution {
public:
vector<int> secondGreaterElement(vector<int>& nums) {
vector<int> secondNextGreater(nums.size(), -1);

// Decreasing monotonic stacks: {num, idx}.
stack<pair<int, int>> stackOne, stackTwo;

vector<pair<int, int>> transporter; // Format: {num, idx}.

for (int idx = 0; idx < nums.size(); idx++) {
int num = nums[idx];

while (!stackTwo.empty() && stackTwo.top().first < num) {
int past_idx = stackTwo.top().second;
secondNextGreater[past_idx] = num;
stackTwo.pop();
}

while (!stackOne.empty() && stackOne.top().first < num) {
transporter.push_back(stackOne.top()); // Keep decreasing monotonicity.
stackOne.pop();
}

while (!transporter.empty()) {
stackTwo.push(transporter.back());
transporter.pop_back();
}

stackOne.push({num, idx});
}

return secondNextGreater;
}
};
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
105 changes: 105 additions & 0 deletions solution/2400-2499/2454.Next Greater Element IV/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -831,3 +831,108 @@ class TreeMultiSet<T = number> {
<!-- solution:end -->

<!-- problem:end -->

### Solution 2: Double Stacks
We maintain two decreasing monotonic stacks:

```stackOne```: stores elements that have not yet encountered any greater element to their right.

```stackTwo```: stores elements that have encountered exactly one greater element to their right.

Algorithm:

As we iterate through the array ```nums```, for current element $nums[k]$, have these steps:

1. While ```stackTwo``` is not empty and its top element is less than $nums[k]$,
these top elements have found their second next greater element.
Pop them and record $nums[k]$ as the answer for their respective indices.

2. While ```stackOne``` is not empty and its top element is less than $nums[k]$,
these top elements have found their first next greater element.
Pop them to move them to a temporary list/vector called ```transporter```.

3. Pop all elements from the back of ```transporter``` and push them onto ```stackTwo```.
These elements will naturally maintain the decreasing order in ```stackTwo```.

4. Push current element $nums[k]$ into ```stackOne``` for future comparisons.

Our time complexity is $O(n)$, where $n$ is the length of the array nums.

This is because each element is pushed and popped across two stacks for at most 4 times in total.

Space complexity is $O(n)$, as all elements must be stored across two stacks.

<!-- tabs:start -->

#### Python3

```python
class Solution:
def secondGreaterElement(self, nums: list[int]) -> list[int]:
second_next_greater = [-1] * len(nums)

stack_1: list[tuple[int, int]] = [] # Decreasing monotonic stacks: (num, idx).
stack_2: list[tuple[int, int]] = []

transporter: list[tuple[int, int]] = [] # Transport tuples from stack 1 to stack 2.

for idx, num in enumerate(nums):
while stack_2 and stack_2[-1][0] < num:
_, past_idx = stack_2.pop(-1)
second_next_greater[past_idx] = num

while stack_1 and stack_1[-1][0] < num:
transporter.append(stack_1.pop(-1))

while transporter:
stack_2.append(transporter.pop(-1)) # Ensure decreasing monotonicity.
stack_1.append((num, idx))

return second_next_greater
```

#### C++

```cpp
class Solution {
public:
vector<int> secondGreaterElement(vector<int>& nums) {
vector<int> secondNextGreater(nums.size(), -1);

// Decreasing monotonic stacks: {num, idx}.
stack<pair<int, int>> stackOne, stackTwo;

vector<pair<int, int>> transporter; // Format: {num, idx}.

for (int idx = 0; idx < nums.size(); idx++) {
int num = nums[idx];

while (!stackTwo.empty() && stackTwo.top().first < num) {
int past_idx = stackTwo.top().second;
secondNextGreater[past_idx] = num;
stackTwo.pop();
}

while (!stackOne.empty() && stackOne.top().first < num) {
transporter.push_back(stackOne.top()); // Keep decreasing monotonicity.
stackOne.pop();
}

while (!transporter.empty()) {
stackTwo.push(transporter.back());
transporter.pop_back();
}

stackOne.push({num, idx});
}

return secondNextGreater;
}
};
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
35 changes: 35 additions & 0 deletions solution/2400-2499/2454.Next Greater Element IV/Solution2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Solution {
public:
vector<int> secondGreaterElement(vector<int>& nums) {
vector<int> secondNextGreater(nums.size(), -1);

// Decreasing monotonic stacks: {num, idx}.
stack<pair<int, int>> stackOne, stackTwo;

vector<pair<int, int>> transporter; // Format: {num, idx}.

for (int idx = 0; idx < nums.size(); idx++) {
int num = nums[idx];

while (!stackTwo.empty() && stackTwo.top().first < num) {
int past_idx = stackTwo.top().second;
secondNextGreater[past_idx] = num;
stackTwo.pop();
}

while (!stackOne.empty() && stackOne.top().first < num) {
transporter.push_back(stackOne.top()); // Keep decreasing monotonicity.
stackOne.pop();
}

while (!transporter.empty()) {
stackTwo.push(transporter.back());
transporter.pop_back();
}

stackOne.push({num, idx});
}

return secondNextGreater;
}
};
23 changes: 23 additions & 0 deletions solution/2400-2499/2454.Next Greater Element IV/Solution2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution:
def secondGreaterElement(self, nums: list[int]) -> list[int]:
second_next_greater = [-1] * len(nums)

stack_1: list[tuple[int, int]] = [] # Decreasing monotonic stacks: (num, idx).
stack_2: list[tuple[int, int]] = []

# Transport tuples from stack 1 to stack 2.
transporter: list[tuple[int, int]] = []

for idx, num in enumerate(nums):
while stack_2 and stack_2[-1][0] < num:
_, past_idx = stack_2.pop(-1)
second_next_greater[past_idx] = num

while stack_1 and stack_1[-1][0] < num:
transporter.append(stack_1.pop(-1))

while transporter:
stack_2.append(transporter.pop(-1)) # Ensure decreasing monotonicity.
stack_1.append((num, idx))

return second_next_greater
Loading