给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
提示:
1 <= nums1.length <= nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 104
nums1和nums2中所有整数 互不相同
nums1 中的所有整数同样出现在 nums2 中
单调栈代码:
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> s;
unordered_map<int,int> res;//存对应nums2的next greater number问题的结果数组,后面对于nums1直接取数,然后读
vector<int>ans;
int n = nums1.size(), m = nums2.size();
for (int i = m - 1; i >= 0; --i)
{//倒着往栈里面加数据,加进去的应该是从上到下的一个单调递增的序列
while (!s.empty() && s.top() <= nums2[i])//如果这个新加进来的数据比之前加进来的大,那么弹出之前加进来的,只有最大的才能在下面
s.pop();
res[nums2[i]] = s.empty() ? -1 : s.top();
s.push(nums2[i]);
}
for (int i = 0; i < n; i++)
ans.push_back(res.at(nums1[i]));
return ans;
}
};
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
示例 1:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int m = nums.size();
for (int i = 0; i < m; i++)nums.push_back(nums[i]);
//把循环数组实现,连接一个,就和正常的单调栈一样了,但是这个方法不好
vector<int>res(2*m);
vector<int>ans;
stack<int>s;
for (int i = 2*m - 1; i >= 0; --i)
{
while (!s.empty() && s.top() <= nums[i])
s.pop();
res[i] = s.empty() ? -1 : s.top();
s.push(nums[i]);
}
for (int i = 0; i < m; i++)
ans.push_back(res[i]);
return ans;
}
};
方法2
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
vector<int> ret(n, -1);
stack<int> stk;
for (int i = 0; i < n * 2 - 1; i++) {
//顺序入栈的方法,这样不必显式做到连接两次数组,可以用取余的方法
while (!stk.empty() && nums[stk.top()] < nums[i % n]) {
ret[stk.top()] = nums[i % n];
stk.pop();
}
stk.push(i % n);
}
return ret;
}
};
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
vector<int> dailyTemperatures(vector<int>& T) {
vector<int> res(T.size());
// 这里放元素索引,而不是元素
stack<int> s;
/* 单调栈模板 */
for (int i = T.size() - 1; i >= 0; i--) {
while (!s.empty() && T[s.top()] <= T[i])
s.pop();
// 得到索引间距,索引是从大到小放的所以可以直接-i
res[i] = s.empty() ? 0 : (s.top() - i);
// 将索引入栈,而不是元素,索引入栈,好对比距离
s.push(i);
}
return res;
}
1、倒序入栈
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> s;
unordered_map<int,int> res;//存对应nums2的next greater number问题的结果数组,后面对于nums1直接取数,然后读
vector<int>ans;
int n = nums1.size(), m = nums2.size();
for (int i = m - 1; i >= 0; --i)
{//倒着往栈里面加数据,加进去的应该是从上到下的一个单调递增的序列
while (!s.empty() && s.top() < nums2[i])//如果这个新加进来的数据比之前加进来的大,那么弹出之前加进来的,只有最大的才能在下面
s.pop();
//在这里的时候,相当于每遍历一个i就可以得到一个结果
//因为是知道后面有没有比自己大的,但是顺序遍历不可以
res[nums2[i]] = s.empty() ? -1 : s.top();
s.push(nums2[i]);
}
for (int i = 0; i < n; i++)
ans.push_back(res.at(nums1[i]));
return ans;
}
};
2、顺序入栈
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
vector<int> ret(n, -1);
stack<int> stk;
for (int i = 0; i < n - 1; i++) {
while (!stk.empty() && nums[stk.top()] < nums[i]) {
//顺序插入栈的话就必须是要在栈里面存放下标,
//因为逆序的话相当于后面的结果是先知道的,
//所以到了某个值,是一定知道后面有没有比自己大的,但是正序是不知道的
ret[stk.top()] = nums[i];
stk.pop();
}
stk.push(i);
}
return ret;
}
};
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1
输出:[1]
示例 3:
输入:nums = [1,-1], k = 1
输出:[1,-1]
示例 4:
输入:nums = [9,11], k = 2
输出:[11]
示例 5:
输入:nums = [4,-2], k = 2
输出:[4]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
class MonotonicQueue {
//实现一个单调队列
private:
deque<int>data;
public:
void push(int n) {//做的是单调队列的插入操作,单调队列是想要一个单调不增的数值
while (!data.empty() && data.back() < n)//如果新来的数字要大于队列中最后一个
data.pop_back();//就把最后一个弹出
data.push_back(n);//无论如何要把n放进来
}
int max() {
return data.front();
}
void pop(int n) {//弹出队头元素,就是弹出滑动窗口最开始的点
if (!data.empty() && data.front() == n)
data.pop_front();
}
};
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MonotonicQueue window;
vector<int>res;
for (int i = 0; i < nums.size(); i++)
{
if (i < k - 1)
window.push(nums[i]);//先把窗口放k-1个数字
else {
window.push(nums[i]);//再放一个,不要纠结滑动窗口的长度,放一个弹出一个,不会有事的
res.push_back(window.max());//放最大值,取出来,放到结果
window.pop(nums[i - k + 1]);//弹出队头,因为要弹出的数字是距离i为k-1个位置
}
}
return res;
}
};