Leetcode#84 Largest Rectangle in Histogram

题目

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
在这里插入图片描述
The largest rectangle is shown in the shaded area, which has area = 10 unit.

解法

解法一

考虑到最大面积的矩形高度一定跟某个条一样高,所以挨个枚举每个条,看其向左、向右最多能延伸到多远。在计算左右边界时,可以借助之前计算过的结果迭代(类似动归的感觉)优化以减少时间复杂度,这应该算是唯一的难点了。总的来说,向左一遍,向右一遍,整体求面积再一遍,一共需要3次遍历,时间复杂度是O(n)。
左右扫描法非常直观。
来自:https://www.cnblogs.com/boring09/p/4231906.html

代码:

class Solution {
public:
	int largestRectangleArea(vector<int>& hei) {

		int N = hei.size();
		if (N <= 0)
			return 0;
		vector<int> rt(hei.size());
		vector<int> lf(hei.size());

		for (int j = N - 1; j >= 0; --j) {
			rt[j] = 1;
			while (j + rt[j] < N && hei[j]>0 && hei[j + rt[j]] >= hei[j]) {
				rt[j] += rt[j + rt[j]];
			}
		}

		for (int j = 0; j < N; ++j) {
			lf[j] = 1;
			while (j - lf[j] >= 0 && hei[j]>0 && hei[j - lf[j]] >= hei[j]) {
				lf[j] += lf[j - lf[j]];
			}
		}
		int ans = 0;
		for (int j = 0; j < N; j++) {
			ans = max(ans, (rt[j] + lf[j] - 1)*hei[j]);
		}
		return ans;
	}
};

下面给出 复杂度证明
我们只看第一遍从右往左遍历这个过程,
假说是第 n/k 处(k可以是小数) 很辛苦一个一个往右找了 n/p (1/k + 1/p <=1 )个点,那么此时

  • [0, n/k]里大于等于hei[n/k]的点,其复杂度总和是 T(n/k)
  • [0, n/k]里小于hei[n/k]的点,其复杂度总和是 T(n/k)+ O((n-n/k) - n/p)
    • 相当于把[n/k, n/k+n/p]之间的点抹掉,而且对于后面那一串 n-n/k) - n/p个点,最多再往右边跳n-n/k) - n/p

鉴于 (n-n/k) - n/p >= 0, 因此 T(n/k)+ O((n-n/k) - n/p) > T(n/k),
所以对于 [0, n/k] 所有点的复杂度总和为: T(n/k)+ O((n-n/k) - n/p)
此时有:T(n) = T(n/k)+ O((n-n/k) - n/p) + O(n-n/k) + O(n/p) = T(n/k)+ O(n-n/k) ==> T(n) = O(n)
当然上面这个式子成立还应该再加一个前提假设:第 n/k 处的点是最右边那个往右跳且跳的次数达到了O(n)量级的。O(n)量级已经是最大的可能。如果是其他关于n的函数,那么最终复杂度必然小于O(n)。

解法二

参考:https://www.cnblogs.com/boring09/p/4231906.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值