0496. 下一个更大元素 I Next Greater Element I
暴力法
思路比较简单:
- 遍历 nums1 数组中的所有元素, 当前元素为 x
- 遍历 nums2 数组中的所有元素, 找到第一个与 x 相等的元素, 然后向右继续遍历, 找到第一个比 x 大的元素
这个算法的时间复杂度是 O(n^2).
算法实现如下:
#![allow(unused)] fn main() { /// Brute force pub fn next_greater_element1(nums1: Vec<i32>, nums2: Vec<i32>) -> Vec<i32> { // 用于记录每次遍历时的状态. #[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] enum State { /// 没有找到相等的值 #[default] NotFound, /// 找到了相等的值 FoundEqual, /// 找到了相等的值, 同时在它的右侧也找到了更大的值 FoundGreater, } let mut out = Vec::with_capacity(nums1.len()); for x in nums1 { let mut state = State::NotFound; for &y in &nums2 { if state == State::NotFound && y == x { state = State::FoundEqual; } if state == State::FoundEqual && y > x { out.push(y); state = State::FoundGreater; } } if state != State::FoundGreater { out.push(-1); } } out } }
单调栈
因为要在 nums2 数组中找到当前元素, 以及当前元素右侧第一个更大的元素, 这个比较符合单调栈的操作.
具体操作是:
- 先遍历数组 nums2, 构造单调递增栈; 同时创建一个哈稀表, 用于存储
(当前元素值, 当前元素右侧第一个大的元素值)
映射关系map
- 如果当前元素比栈顶元素小, 直接入栈
- 否则说明当前元素比栈顶元素大, 依次将栈顶元素出栈, 并存入
map
中. 这个栈顶元素的右侧第一个大的元素值就是当前元素
- 之后遍历 nums1 数组, 从
map
哈稀表中找到对应的更大的元素, 如果没有的话, 就存储为-1
算法实现如下:
#![allow(unused)] fn main() { use std::collections::HashMap; /// 使用单调栈 pub fn next_greater_element2(nums1: Vec<i32>, nums2: Vec<i32>) -> Vec<i32> { let mut monotonic_stack = Vec::with_capacity(nums2.len()); assert!(!nums2.is_empty()); let mut max_num = i32::MAX; let mut map = HashMap::new(); // 构造递增式单调栈 for &num in &nums2 { if num < max_num { // 将较小的元素入栈 max_num = num; monotonic_stack.push(num); } else { // 将较小的元素出栈 while !monotonic_stack.is_empty() && monotonic_stack[monotonic_stack.len() - 1] < num { let top = monotonic_stack.pop().unwrap(); map.insert(top, num); } // 将当前元素入栈 monotonic_stack.push(num); } } let out = nums1 .iter() .map(|num1| map.get(num1).copied().unwrap_or(-1)) .collect(); out } }
C++ 实现如下:
#include <cassert>
#include <climits>
#include <iostream>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
std::vector<int> nextGreaterElement(std::vector<int>& nums1, std::vector<int>& nums2) {
std::stack<int> monotonic_stack;
std::unordered_map<int, int> map;
int max_num = INT_MAX;
// 构造递增式单调栈
for (int num2 : nums2) {
if (num2 < max_num) {
// 将较小的元素入栈
max_num = num2;
monotonic_stack.push(num2);
} else {
// 将较小的元素出栈
while (!monotonic_stack.empty() && monotonic_stack.top() < num2) {
const int top = monotonic_stack.top();
monotonic_stack.pop();
map.emplace(top, num2);
}
// 将当前元素入栈
monotonic_stack.push(num2);
}
}
std::vector<int> out;
for (int num1 : nums1) {
auto iter = map.find(num1);
if (iter == map.cend()) {
out.push_back(-1);
} else {
out.push_back(iter->second);
}
}
return out;
}
void checkSolution() {
{
std::vector<int> nums1 = {4, 1, 2};
std::vector<int> nums2 = {1, 3, 4, 2};
std::vector<int> expected = {-1, 3, -1};
assert(nextGreaterElement(nums1, nums2) == expected);
}
{
std::vector<int> nums1 = {2, 4};
std::vector<int> nums2 = {1, 2, 3, 4};
std::vector<int> expected = {3, -1};
assert(nextGreaterElement(nums1, nums2) == expected);
}
{
std::vector<int> nums1 = {1, 3, 5, 2, 4};
std::vector<int> nums2 = {6, 5, 4, 3, 2, 1, 7};
std::vector<int> expected = {7, 7, 7, 7, 7};
assert(nextGreaterElement(nums1, nums2) == expected);
}
}
int main() {
checkSolution();
return 0;
}