勾勒最大矩形(leetcode)

 题目链接:LCR 039. 柱状图中最大的矩形 - 力扣(LeetCode)

首先我写题喜欢暴力解法,可以先尝试一下枚举的方法。

这里有两种

第一种:

#include <iostream>
#include <stack>
#include <vector>

using namespace std;
typedef pair<int, int> PII;

int main() {
	int n;
	cin >> n;
	vector<int>v(n);
	int ans = -1;
	int result = 0;
	for (int i = 0; i < n; i++) {
		cin >> v[i];
	}
	//遍历枚举高的算法
	int mid = 0;
	for (; mid < n; mid++) {
		int left = mid;
		int right = mid;
		while (left-1 >= 0 && v[left - 1] >= v[mid]) {
			left--;
		}

		while (right+1<=n-1 && v[right + 1] >= v[mid]) {
			right++;
		}

		

		ans = max(ans, (right - left + 1) * v[mid]);

	}

	cout << ans << endl;
return 0;
}

遍历枚举每一条高线然后从头枚举到尾巴,然后利用循环找到,比他小的两条柱子

但是很显然会超时

第二种方法:

确定宽度,定义一个变量不断的去找最小的高度长度

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <stack>
#include <vector>

using namespace std;
typedef pair<int, int> PII;

int main() {
	int n;
	cin >> n;
	vector<int>v(n);
	int ans = -1;
	int result = 0;
	for (int i = 0; i < n; i++) {
		cin >> v[i];

//遍历枚举宽的算法
int left = 0;
int right = 0;
int min_high = v[0];
for (left; left < n;left++) {

	min_high = INT32_MAX;//重塑一遍,因为不能保留上次的数据

	for (right=left; right < n; right++) {
		
			 min_high = min(v[right], min_high);
		
		result = min_high * (right - left + 1);
		ans = max(ans,result);

	}
}

cout << ans << endl;


return 0;
	}

这里要注意的是,left的变化,记得变化高

然后就是本题的核心思想,单调栈,怎么想出来的呢,就是,请看第一种方法,就是找到比当前小的高,也就是如果,i<j,并且h[i]>h[j]的话,那么我们可以认为,我们在找,就j+1的柱子高度小的柱子,就没有必要在找i了,所以想到用单调栈

先来一个错误的写法(没有实现,当比较完之后,栈里面剩下的数字的处理,以及很难处理,开始的矩形高度是0的问题)

ps:可能是使用的方法不不对,就是利用栈<pair>储存东西

typedef pair<int, int> PII;
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        int ans = -1;
        int result = 0;
        stack<PII>s;
s.push(PII(0, heights[0]));
int Index = 1;//访问元素下标

while (Index < n) {
	if (heights[Index] >= s.top().second) {
		s.push(PII(Index, heights[Index]));
		Index++;
	}
	else {

		result = (Index - (s.top().first))*(s.top().second);
		ans = max(result, ans);
		s.pop();

	}

	if (s.empty()) {
		result = (Index +1) *heights[Index];
		ans = max(result, ans);
		s.push(PII(Index,heights[Index]));
		Index++;
	}

}
int bottle = 0;
int bottleHigh = 0;
if (!s.empty()) {
	int top = s.top().first;
	while (!s.empty()) {
		 if(s.top().second!=0)
		 bottle = s.top().first;
		 if(s.top().second!=0)
		 bottleHigh = s.top().second;
		 s.pop();
	}
	result = (top - bottle + 1) * bottleHigh;
	ans = max(ans, result);
}
	return ans;
    }
};

其实不难发现,一开始的代码连题解的意思都没有搞懂,这个是类比方法一中的方法,去,模拟方法一然后去,找到对应的长度。

改进之后的代码,用vector存储,left和right,以及只用stack来存储相应的下标

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        int ans = -1;
        int result = 0;
      stack<int>s;
vector<int>left(n);
vector<int>right(n);

for (int i = 0; i < n; i++) {
	if (!s.empty() && heights[i] >heights[s.top()]) {
		left[i] = i - 1;
		s.push(i);
	}
	else {
		if (!s.empty()) {
			while (!s.empty()&&heights[i]<=heights[s.top()]) {
				s.pop();
			}
		}
		left[i] = (s.empty() ? -1 : s.top());
		s.push(i);
	}
}

s = stack<int>();

for (int i = n-1; i >= 0; i--) {
	if (!s.empty() && heights[i] > heights[s.top()]) {
		right[i] = i + 1;
		s.push(i);
	}
	else {
		if (!s.empty()) {
			while (!s.empty() && heights[i] <= heights[s.top()]) {
				s.pop();
			}
		}
		right[i] = (s.empty() ? n : s.top() );
		s.push(i);
	}

}

for (int i = 0; i < n; i++) {
	result = (right[i] - left[i] - 1) * heights[i];
	ans = max(ans, result);
}
	return ans;
    }
};

有几个地方很重要

如图

然后就是一些小细节

清空栈啊,!empty()要放当成优先级最高的条件,不然可能会访问越界

然后就是一些访问越界问题,注意一下就好了

下面是官方代码:比我的简洁但我想不到

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值