【LeetCode】84.柱狀圖中最大的矩形
阿新 • • 發佈:2020-12-26
題目連結
84. 柱狀圖中最大的矩形
題目描述
解題思路
暴力法
對於每一個高度height[i],我們可以向左向右遍歷,然後算出該高度往左往右最多可以延申至何處,這樣就能算出該高度對應的面積,列舉所有高度然後求出最大值。
時間複雜度:O(n)
空間複雜度:O(1)
超時!
單調棧
以上暴力寫法 Java 可以通過,但我們不妨想一下這裡的雙重迴圈是否可以優化?
我們每遍歷到當前柱體 i 時:暴力解法中我們需要再巢狀一層 while 迴圈來向左找到第一個比柱體 i 高度小的柱體,這個過程是 O(N) 的;
那麼我們可以 O(1)的獲取柱體 i 左邊第一個比它小的柱體嗎?答案就是單調增棧,因為對於棧中的柱體來說,棧中下一個柱體就是左邊第一個高度小於自身的柱體。
因此做法就很簡單了,我們遍歷每個柱體,若當前的柱體高度大於等於棧頂柱體的高度,就直接將當前柱體入棧,否則若當前的柱體高度小於棧頂柱體的高度,說明當前棧頂柱體找到了右邊的第一個小於自身的柱體,那麼就可以將棧頂柱體出棧來計算以其為高的矩形的面積了。
小trick:為長度陣列首位加上兩個0,便於計算,同時可以解決高度遞增序列現象問題。
AC程式碼
暴力法
class Solution { public int largestRectangleArea(int[] heights) { int area = 0, n = heights.length; // 遍歷每個柱子,以當前柱子的高度作為矩形的高 h, // 從當前柱子向左右遍歷,找到矩形的寬度 w。 for (int i = 0; i < n; i++) { int w = 1, h = heights[i], j = i; while (--j >= 0 && heights[j] >= h) { w++; } j = i; while (++j < n && heights[j] >= h) { w++; } area = Math.max(area, w * h); } return area; } }
單調棧法
class Solution { public int largestRectangleArea(int[] heights) { int ans = 0; int cHeights[] = new int[heights.length+2]; cHeights[0] = 0; cHeights[heights.length+1] = 0; for(int i = 1; i < heights.length+1; i++){ cHeights[i] = heights[i-1]; } Stack<Integer> st = new Stack<>(); for(int i = 0; i < cHeights.length; i++){ while(!st.isEmpty() && cHeights[i] < cHeights[st.peek()]){ int height = cHeights[st.pop()]; ans = Math.max(ans,height * (i - st.peek() - 1)); } st.push(i); } return ans; } }