[Swift]LeetCode84. 柱状图中最大的矩形 | Largest Rectangle in Histogram

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

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.

[Swift]LeetCode84. 柱状图中最大的矩形 | Largest Rectangle in Histogram
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

[Swift]LeetCode84. 柱状图中最大的矩形 | Largest Rectangle in Histogram
The largest rectangle is shown in the shaded area, which has area = 10 unit.

Example:

Input: [2,1,5,6,2,3]
Output: 10

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

[Swift]LeetCode84. 柱状图中最大的矩形 | Largest Rectangle in Histogram

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]

[Swift]LeetCode84. 柱状图中最大的矩形 | Largest Rectangle in Histogram

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

示例:

输入: [2,1,5,6,2,3]
输出: 10

44ms
 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3             
 4     if heights.count == 0 {
 5         return 0
 6     }
 7         
 8             if heights.count == 1 {
 9         return heights[0]
10     }
11     var leftIndexes = Array<Int>.init(repeating: 0, count: heights.count)
12     var rightIndexes = Array<Int>.init(repeating: 0, count: heights.count)
13     leftIndexes[0] = -1
14     rightIndexes[heights.count - 1] = heights.count
15     
16     for i in 1..<heights.count {
17         var p = i - 1
18         while p >= 0, heights[p] >= heights[i] {
19             p = leftIndexes[p]
20         }
21         leftIndexes[i] = p
22     }
23     
24     for i in (0...heights.count - 2).reversed() {
25         var p = i + 1
26         while p < heights.count, heights[p] >= heights[i] {
27             p = rightIndexes[p]
28         }
29         rightIndexes[i] = p
30     }
31     var maxArea = 0
32     for i in 0..<heights.count {
33         maxArea = max(maxArea, heights[i] * (rightIndexes[i] - leftIndexes[i] - 1))
34     }
35 
36     return maxArea
37     }
38 }

64ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         
 4         let heights = heights + [0]
 5         
 6         var indexStack: [Int] = []
 7         var maxHeight = 0
 8         
 9         for (i,height) in heights.enumerated() {
10             
11             while let previousIndex = indexStack.last, heights[previousIndex] > height {
12                 indexStack.removeLast()
13                 
14                 let lastIndex = indexStack.last ?? -1
15                 let width = (i-1) - lastIndex
16                 let height = heights[previousIndex]
17                 
18                 maxHeight = max(maxHeight, width * height)
19             }
20             
21             indexStack.append(i)
22         }
23         
24         return maxHeight
25     }
26 }

72ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         
 4         var stack = [Int]()
 5         var bestSolution = 0
 6         var currentHeight = 0
 7         
 8         for i in 0..<heights.count {
 9             
10             currentHeight = heights[i]
11             if currentHeight > bestSolution {
12                 //bestSolution = currentHeight
13             }
14             
15             while stack.last != nil && currentHeight <= heights[stack.last!]  {
16                 
17                 var lastIndex = stack.last!
18                 var lastHeight = heights[lastIndex]
19                 stack.removeLast()
20                 
21                 var index = stack.isEmpty ? i : (i - 1 - stack.last!)
22                 var rectHeight = lastHeight * (index)
23                 
24                 if rectHeight > bestSolution {
25                     bestSolution = rectHeight
26                 }
27             }
28             
29             stack.append(i)
30         }
31         
32         while stack.last != nil {
33             
34             var lastIndex = stack.last!
35             var lastHeight = heights[lastIndex]
36             stack.removeLast()
37                 
38             var index = stack.isEmpty ? (heights.count) : ((heights.count) - 1 - stack.last!)
39             var rectHeight = lastHeight * (index)
40             
41             if rectHeight > bestSolution {
42                 bestSolution = rectHeight
43             }
44         }
45         
46         return bestSolution
47     }
48 }

76ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         
 4         if heights.count == 0 {
 5             return 0
 6         }
 7         
 8         var myHeights: [Int] = heights
 9         myHeights.append(0)
10 
11         var s = 0
12         var stack: [Int] = []
13         var i = 0
14         
15         while i < myHeights.count {
16             
17             if stack.count == 0 || myHeights[stack.last!] < myHeights[i] {
18                 
19                 stack.append(i)
20                 i += 1
21             } else {
22                 
23                 let j = stack.last!
24                 stack.removeLast()
25                 
26                 s = max(s, myHeights[j]*(stack.isEmpty ? i : i - 1 - stack.last!))
27    
28             }
29         }
30         
31         return s
32     }
33 }

88ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         var left: [Int] = Array(repeating: 0, count: heights.count)
 4         var right: [Int] = Array(repeating: 0, count: heights.count)
 5         var sums: [Int] = Array(repeating: 0, count: heights.count)
 6         
 7         for index in 0..<heights.count {
 8             var indexToLeft = index
 9             while indexToLeft > 0 {
10                 if heights[indexToLeft - 1] >= heights[index] {
11                     indexToLeft -= 1 + left[indexToLeft-1]
12                 } else {
13                     break
14                 }
15             }
16             
17             left[index] = index-indexToLeft
18         }
19         
20         for index in (0..<heights.count).reversed() {
21             var indexToRight = index
22             while (indexToRight + 1) < heights.count {
23                 if heights[indexToRight + 1] >= heights[index] {
24                     indexToRight += 1 + right[indexToRight+1]
25                 } else {
26                     break
27                 }
28             }
29             
30             right[index] = indexToRight - index
31         }
32         
33         var maxSum = 0
34         for index in 0..<heights.count {
35             sums[index] = heights[index] * (left[index] + 1 + right[index])
36             maxSum = max(maxSum, sums[index])
37         }
38         return maxSum        
39     }
40 }

96ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         var stack = [Int]()
 4         var max = 0
 5         for i in 0..<heights.count {
 6             if stack.count == 0 || heights[i]>=heights[stack[stack.count-1]] {
 7                 stack.append(i)
 8             } else {
 9                 while stack.count > 0 && heights[i] < heights[stack[stack.count-1]] {
10                     let area = eval(&stack, heights, i)
11                     if area > max {
12                         max = area
13                     }
14                 }
15                 stack.append(i)
16             }
17         }
18         while stack.count > 0 {
19             let area = eval(&stack, heights, heights.count)
20             if area > max {
21                 max = area
22             }
23         }
24         return max
25     }
26     
27     func eval(_ stack: inout [Int], _ heights: [Int], _ end: Int) -> Int {
28         let idx = stack.last!
29         stack.removeLast()
30         var area = 0
31 
32         if let start = stack.last {
33             area = heights[idx]*(end-start-1)
34         } else {
35             area = heights[idx]*end
36         }
37         return area
38     }
39 }

148ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         if heights.isEmpty {return 0}
 4         var stack = [0], maxArea = 0
 5         var i = 1
 6         while i < heights.count || !stack.isEmpty {
 7             if i < heights.count && (stack.isEmpty || heights[i] >= heights[stack.last!]) {
 8                 stack.append(i)
 9                 i += 1
10             } else {
11                 let curr = stack.popLast()!
12                 let leftBound = stack.isEmpty ? -1 : stack.last!
13                 let currArea = heights[curr] * (i - 1 - leftBound)
14                 maxArea = max(maxArea, currArea)
15             }
16         }
17         return maxArea
18     }
19 }

236ms

 1 class Solution {
 2     func largestRectangleArea(_ heights: [Int]) -> Int {
 3         var stack = [Int]()
 4         var res = 0
 5         for i in 0...heights.count {
 6             let curr = i == heights.count ? 0 : heights[i]
 7             while !stack.isEmpty && heights[stack[0]] > curr {
 8                 let height = heights[stack.removeFirst()]
 9                 let width = stack.isEmpty ? i : i - 1 - stack[0]
10                 res = max(res, height * width)
11             }
12             stack.insert(i, at: 0)
13         }
14         return res
15     }
16 }