2022兴业银行笔试题
暴力法(超时)
核心思想就是左右两开花,向左和向右分别找到大于等于自己的数字,然后记录下位置,在比较自己面积和左右面积之和。
public class Solution {
public int largestRectangleArea(int[] heights) {
int len = heights.length;
if (len == 0) {
return 0;
}
int res = 0;
for (int i = 0; i < len; i++) {
// 找左边最后 1 个大于等于 heights[i] 的下标
int left = i;
int curHeight = heights[i];
while (left > 0 && heights[left - 1] >= curHeight) {
left--;
}
// 找右边最后 1 个大于等于 heights[i] 的索引
int right = i;
while (right < len - 1 && heights[right + 1] >= curHeight) {
right++;
}
int width = right - left + 1;
res = Math.max(res, width * curHeight);
}
return res;
}
}
复杂度分析:
时间复杂度:O(N^2)O(N )2
),这里 NN 是输入数组的长度。
空间复杂度:O(1)O(1)
单调栈
单调栈
单调栈分为单调递增栈和单调递减栈
11. 单调递增栈即栈内元素保持单调递增的栈
12. 同理单调递减栈即栈内元素保持单调递减的栈
操作规则(下面都以单调递增栈为例)
21. 如果新的元素比栈顶元素大,就入栈
22. 如果新的元素较小,那就一直把栈内元素弹出来,直到栈顶比新元素小
加入这样一个规则之后,会有什么效果
31. 栈内的元素是递增的
32. 当元素出栈时,说明这个新元素是出栈元素向后找第一个比其小的元素
举个例子,配合下图,现在索引在 6 ,栈里是 1 5 6
接下来新元素是 2 ,那么 6 需要出栈。
当 6 出栈时,右边 2 代表是 6 右边第一个比 6 小的元素。
当元素出栈后,说明新栈顶元素是出栈元素向前找第一个比其小的元素
当 6 出栈时,5 成为新的栈顶,那么 5 就是 6 左边第一个比 6 小的元素。
代码模板
C++
stack<int> st;
for(int i = 0; i < nums.size(); i++)
{
while(!st.empty() && st.top() > nums[i])
{
st.pop();
}
st.push(nums[i]);
}
画图理解
思路
1 对于一个高度,如果能得到向左和向右的边界
2 那么就能对每个高度求一次面积
3 遍历所有高度,即可得出最大面积
4 使用单调栈,在出栈操作时得到前后边界并计算面积
class Solution {
public int largestRectangleArea(int[] heights) {
int res = 0;
Deque<Integer> stack = new ArrayDeque<>();
int[] new_heights = new int[heights.length + 2];
for (int i = 1; i < heights.length + 1; i++) {
new_heights[i] = heights[i - 1];
}
for (int i = 0; i < new_heights.length; i++) {
while (!stack.isEmpty() && new_heights[stack.peek()] > new_heights[i]) {
int cur = stack.pop();
int l = stack.peek();
int r = i;
res = Math.max(res, (r - l - 1) * new_heights[cur]);
}
stack.push(i);
}
return res;
}
}
复杂度分析:
时间复杂度:O(N),输入数组里的每一个元素入栈一次,出栈一次。
空间复杂度:O(N),栈的空间最多为 N。