题目
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
思路
1、辅助栈
根据之前一题所讲的辅助栈的思想,通常是除了所有元素所在栈之外,另开辟新的栈存储一些变量。对于本题,辅助栈的意义在于暂时存放那些从栈中弹出用于比较的元素。
(1)遍历nums2,将其全部放入stack1中;
(2)取出stack1的栈顶元素,将其与nums1数组中的数比较,若大,则更新max——“下一个更大元素”,若相等,则说明已经找完目标元素之后的每个数,需停止遍历,若小,则不做处理;之后将取出的栈顶元素压入辅助栈stack2中。
(3)随着遍历更新max,最终找到距离最近的“下一个”更大元素,将其放入数组中;
(4)为了方便对nums1数组中的下一个元素进行同样的操作,再将辅助栈stack2中的每个元素放回stack1中;
(5)遍历nums1数组,执行(2)(3)(4);
2、单调栈,即一个栈内元素从栈顶到栈底具有单调性的栈,在利用这个方法时,不像前一种方法先一股脑的将nums2全部入栈,而是将要入栈的元素与栈顶元素进行比较,如果即将要入栈的元素大,则表示已经找到了“下一个更大元素”,就将栈顶元素出栈,和即将入栈的元素一起存入哈希表中构成映射关系,这样nums1中的元素只需要去哈希表中找对应元素即可。
(1)遍历nums2数组,在栈为空时,将nums2[i]入栈;
(2)在栈不为空且即将入栈的元素>栈顶元素时,弹出栈顶元素,与即将入栈的元素一起存入哈希表中;然后再将这个即将入栈的元素真正入栈;
(3)遍历完成nums2数组,构建完成哈希映射
(4)如果即将入栈的元素不大于栈顶元素,那么它就会直接入栈,如果遍历完数组之后,栈中还有元素,则说明这些元素不存在“下一个更大元素”,便把它们加入哈希表中映射为-1;
求解方法
1、辅助栈
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
//辅助栈;时间复杂度O(MN),用到了双层循环,空间复杂度O(N)
vector<int>result;
stack<int>st;
stack<int>temp;
int top;
for (int i = 0; i < nums2.size(); i++)
{
st.push(nums2[i]);
}
for (int i = 0; i < nums1.size(); i++)
{
int max = -1;
bool isFound = false;
while (!st.empty() && !isFound)
{
top = st.top();
st.pop();
if (top > nums1[i]) max = top;
else if (top == nums1[i]) isFound = true;
temp.push(top);
}
result.push_back(max);
while (!temp.empty())
{
int m_top = temp.top();
st.push(m_top);
temp.pop();
}
}
return result;
}
2、单调栈
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> st;
map<int, int> m_map;
vector<int> result;
for (int i = 0; i < nums2.size(); i++)
{
while (!st.empty() && nums2[i] > st.top())
{
m_map[st.top()] = nums2[i];
st.pop();
}
st.push(nums2[i]);
}
while (!st.empty())
{
int temp = st.top();
m_map[temp] = -1;
st.pop();
}
for (int i = 0; i < nums1.size(); i++)
{
result.push_back(m_map[nums1[i]]);
}
return result;
}