题目描述

力扣题目链接
image.png

解题思路

具体参照:carl的题解
主要和接雨水不同的是求的是两边小于中间。

双指针(超时)

  1. /**
  2. * 双指针法(超时)
  3. *
  4. * @param heights
  5. * @return
  6. */
  7. public int largestRectangleArea(int[] heights) {
  8. int maxSize = 0;
  9. for (int i = 0; i < heights.length; i++) {
  10. int leftIndex = i;
  11. int rightIndex = i;
  12. // 找到小于i的高度
  13. for (; leftIndex >= 0; leftIndex--) {
  14. if (heights[leftIndex] < heights[i]) break;
  15. }
  16. for (; rightIndex < heights.length; rightIndex++) {
  17. if (heights[rightIndex] < heights[i]) break;
  18. }
  19. int high = heights[i];
  20. int width = rightIndex - leftIndex - 1;
  21. maxSize = Math.max(maxSize, high * width);
  22. }
  23. return maxSize;
  24. }

动态规划

  1. /**
  2. * 动态规划
  3. *
  4. * @param heights
  5. * @return
  6. */
  7. public int largestRectangleArea(int[] heights) {
  8. int[] minLeftIndex = new int[heights.length];
  9. int[] minRightIndex = new int[heights.length];
  10. int maxSize = 0;
  11. // 记录每个柱子 左边第一个小于该柱子的下标
  12. minLeftIndex[0] = -1; // 注意这里初始化,防止下面while死循环
  13. for (int i = 1; i < heights.length; i++) {
  14. int t = i - 1;
  15. // 这里不是用if,而是不断向左寻找的过程
  16. while (t >= 0 && heights[t] >= heights[i])
  17. t = minLeftIndex[t]; // while一直循环找到左边第一个小于该柱子的下标
  18. minLeftIndex[i] = t;
  19. }
  20. minRightIndex[heights.length - 1] = heights.length;
  21. for (int i = heights.length - 2; i >= 0; i--) {
  22. int t = i + 1;
  23. // 这里不是用if,而是不断向左寻找的过程
  24. while (t < heights.length && heights[t] >= heights[i])
  25. t = minRightIndex[t]; // 记录每个柱子 右边第一个小于该柱子的下标
  26. minRightIndex[i] = t;
  27. }
  28. // 求和
  29. for (int i = 0; i < heights.length; i++) {
  30. int size = heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1);
  31. if (size > maxSize) maxSize = size;
  32. }
  33. return maxSize;
  34. }

⭐单调栈

  1. public int largestRectangleArea(int[] heights) {
  2. // 数组扩容,在头尾各加一个元素
  3. int[] array = new int[heights.length + 2];
  4. array[0] = 0;
  5. array[heights.length + 1] = 0;
  6. for (int i = 0; i < heights.length; i++) {
  7. array[i + 1] = heights[i];
  8. }
  9. Stack<Integer> stack = new Stack<>();
  10. stack.push(0); // 栈顶到栈底,从大到小
  11. int maxSize = 0;
  12. heights = array; // 需要在头尾各加一个0,来保证大小为2或者1时特殊情况,和都是相同的数字也是特殊情况
  13. for (int i = 1; i < heights.length; i++) {
  14. if (heights[stack.peek()] < heights[i]) {
  15. stack.push(i);
  16. } else if (heights[stack.peek()] == heights[i]) {
  17. stack.pop();
  18. stack.push(i);
  19. } else {
  20. while (heights[stack.peek()] > heights[i]) {
  21. Integer mid = stack.peek();
  22. stack.pop();
  23. Integer left = stack.peek();
  24. int size = (i - left - 1) * heights[mid];
  25. maxSize = Math.max(size, maxSize);
  26. }
  27. stack.push(i);
  28. }
  29. }
  30. return maxSize;
  31. }