题目链接
代码随想录文章讲解链接
用时:13m52s
维护一个栈底到栈顶是单调递减的栈,从后往前遍历数组nums2,更新栈。nums2当前元素nums2[i]的下一个更大元素就是栈顶元素,若栈顶为空则表示nums2[i]之后没有比他大的元素。用哈希表存储,然后遍历nums1时再从哈希表中获取值。
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> stk;
unordered_map<int, int> hashMap;
vector<int> res(nums1.size(), 0);
for (int i = nums2.size() - 1; i >= 0; --i) {
while (!stk.empty() && nums2[i] > stk.top()) stk.pop();
hashMap[nums2[i]] = stk.empty() ? -1 : stk.top();
stk.push(nums2[i]);
}
for (int i = 0; i < res.size(); ++i) res[i] = hashMap[nums1[i]];
return res;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:16m28s
维护一个栈底到栈顶单调递减的单调栈,遍历两遍数组。
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int size = nums.size();
stack<int> stk;
vector<int> res(size, -1);
for (int i = 0; i < size * 2; ++i) {
while (!stk.empty() && nums[stk.top()] < nums[i % size]) {
res[stk.top()] = nums[i % size];
stk.pop();
}
stk.push(i % size);
}
return res;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:28m51s
分别统计每一列雨水的高度,设某一列i左边最高的柱子高度为L,列i右边最高的柱子高度为R,若min(L,R)大于列i的高度,则列i的雨水量为min(L,R) - height[i]
,否则为0。
先分别记录下每个位置左右两边最高的柱子的高度,然后再统计每一列雨水的高度。
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
vector<int> leftMax(size, 0);
vector<int> rightMax(size, 0);
int maxHeight = 0;
int res = 0;
// 记录每个位置左右两边最高的柱子高度
for (int i = 0; i < size; ++i) {
leftMax[i] = maxHeight;
maxHeight = max(maxHeight, height[i]);
}
maxHeight = 0;
for (int i = size - 1; i >= 0; --i) {
rightMax[i] = maxHeight;
maxHeight = max(maxHeight, height[i]);
}
// 统计每一列的雨水
for (int i = 1; i < size - 1; ++i) {
int minHeight = min(leftMax[i], rightMax[i]);
if (minHeight > height[i]) res += minHeight - height[i];
}
return res;
}
};
用时:13m28s
维护一个栈底到栈顶单调递减的单调栈。
遍历数组的时候,若遇到小于等于栈顶元素的元素,则直接入栈。
若遇到大于栈顶元素的元素,此时栈顶元素作为凹陷处,倒数第二个栈顶元素和当前元素作为两头的柱子,可以形成一个坑接住雨水,接住雨水的量等于(min(height[i], height[stk.top()]) - height[mid]) * (i - stk.top() - 1)
,分别是高乘宽。
class Solution {
public:
int trap(vector<int>& height) {
stack<int> stk;
int res = 0;
for (int i = 0; i < height.size(); ++i) {
while (!stk.empty() && height[i] > height[stk.top()]) {
int mid = stk.top();
stk.pop();
if (!stk.empty()) res += (min(height[i], height[stk.top()]) - height[mid]) * (i - stk.top() - 1);
}
stk.push(i);
}
return res;
}
};
无。
无。
题目链接
代码随想录文章讲解链接
用时:18m4s
以某个柱子为基准,最大矩形面积与该柱子两侧第一个比它矮的柱子的位置有关。
前两次遍历找到每个柱子左右两侧第一个比它矮的柱子的位置。
最后一次遍历计算以各个柱子为基准的最大矩形面积,最大值即为答案。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int size = heights.size();
vector<int> leftMin(size);
vector<int> rightMin(size);
int res = 0;
// 记录每个柱子左边第一个比它小的柱子的位置
leftMin[0] = -1;
for (int i = 1; i < size; ++i) {
int left = i - 1;
while (left >= 0 && heights[left] >= heights[i]) left = leftMin[left];
leftMin[i] = left;
}
// 记录每个柱子右边第一个比它小的柱子的位置
rightMin[size - 1] = size;
for (int i = size - 2; i >= 0; --i) {
int right = i + 1;
while (right < size && heights[right] >= heights[i]) right = rightMin[right];
rightMin[i] = right;
}
// 遍历以每个柱子为基准的矩形大小,记录最大值
for (int i = 0; i < size; ++i) res = max(res, heights[i] * (rightMin[i] - leftMin[i] - 1));
return res;
}
};
用时:33m9s
因为我们要找到某个基准柱子左右两边比它小的柱子的位置,所以药维护一个栈底到栈顶单调递增的单调栈,这样对于栈顶元素的柱子,它左边第一个比它小的柱子就是第二个栈顶元素,右边第一个比它小的元素就是遍历过程中比栈顶元素小的元素。
遍历数组,若元素大于等于栈顶元素,则入栈;若元素小于栈顶元素,则取出栈顶元素作为基准柱子,然后弹出栈顶元素,基准柱子左边第一个比它小的柱子就是此时的栈顶元素,右边第一个比它小的柱子就是当前遍历的元素,然后记录矩形的面积并更新答案。
由于在遍历的过程中,可能会出现栈为空的情况,以及数组本身就是递增数组的情况,此时会有特殊情况需要处理,可以在数组前后各加入一个0,简化逻辑,因为0一定是小于柱子高度,能够作为左右两端最矮的基准柱子的边界。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int> stk;
int res = 0;
heights.insert(heights.begin(), 0);
heights.push_back(0);
stk.push(0);
for (int i = 1; i < heights.size(); ++i) {
while (heights[i] < heights[stk.top()]) {
int mid = stk.top();
stk.pop();
res = max(res, heights[mid] * (i - stk.top() - 1));
}
stk.push(i);
}
return max(res, heights[stk.top()]);
}
};
无。
边界问题处理了半天没搞定,在数组前后各加入一个0的方法真巧妙。
最近都在搞比赛,好久没刷题了,比赛目前搞得差不多了,得接着刷题了。
希望比赛能拿个好成绩,求求求求求求了!