初始化栈的代码_单调栈算法

一、单调栈的概念

从栈底元素到栈顶元素呈单调递增或单调递减,栈内序列满足单调性的栈。

二、单调栈算法举例

LeetCode_84柱状图中最大的矩形(https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)

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

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

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

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

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

3d0b6cf33736ea97d0195bf4c0860e39.png

按照单调栈的思路,递增时入栈,其余时计算面积并出栈,直到继续递增时入栈。面积将通过计算当前位置和栈顶元素所在位置的宽度查,再乘上元素的height值的思路来做这题:

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 两个栈,一个存位置,一个存值
        Stack<Integer> posStack = new Stack<>();
        Stack<Integer> valueStack = new Stack<>();
        posStack.push(-1);
        valueStack.push(-1);

        int maxArea = 0;

        for (int i = 0; i <= heights.length; i++) {
            // 当前值比栈顶大,即压栈
            if (i < heights.length && heights[i] >= valueStack.peek()) {
                posStack.push(i);
                valueStack.push(heights[i]);
            }
            else {
                // 已到头了,挨个向前把每个面积都算一下
                if (i >= heights.length) {
                    while (posStack.peek() != -1) {
                        int value = valueStack.peek();
                        valueStack.pop();
                        posStack.pop();
                        int area = value * (i - posStack.peek() - 1);
                        maxArea = area > maxArea ? area : maxArea;
                    }
                }
                // 未到头时,当前值比栈顶小的,则向前计算面积,直到比栈顶大,压栈
                else {
                    while (heights[i] < valueStack.peek()) {
                        int value = valueStack.peek();
                        valueStack.pop();
                        posStack.pop();
                        int area = value * (i - posStack.peek() - 1);
                        maxArea = area > maxArea ? area : maxArea;
                    }
                    posStack.push(i);
                    valueStack.push(heights[i]);
                }
            }
        }
        return maxArea;
    }

}

这道题说起来花了不少时间,从理解思路,到实际写代码,写代码时有两个用例又没通过,再重新调试对了思路。直到最后现在的结果。

21cca915b6d2e64896d565a27a9c0b8a.png

其实可以做一些代码优化,少一个栈空间,代码做下抽去方法的精简,但其实我觉得没太大的必要,可以看下优化的:

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 初始化栈,存位置-1,压底
        Stack<Integer> posStack = new Stack<>();
        posStack.push(-1);
        // 最大面积
        int maxArea = 0;

        for (int i = 0; i <= heights.length; i++) {
            // 当前值比栈顶大,即压栈
            if (i < heights.length && heights[i] >= (posStack.peek() == -1 ? -1 : heights[posStack.peek()])) {
                posStack.push(i);
            }
            else {
                // 已到头了,挨个向前把每个面积都算一下
                if (i >= heights.length) {
                    while (posStack.peek() != -1) {
                        maxArea = getMaxArea(posStack, maxArea, i, heights[posStack.peek()]);
                    }
                }
                // 未到头时,当前值比栈顶小的,则向前计算面积,直到比栈顶大,压栈
                else {
                    while (heights[i] < (posStack.peek() == -1 ? -1 : heights[posStack.peek()])) {
                        maxArea = getMaxArea(posStack, maxArea, i, (posStack.peek() == -1 ? -1 : heights[posStack.peek()]));
                    }
                    posStack.push(i);
                }
            }
        }
        return maxArea;
    }

    private int getMaxArea(Stack<Integer> posStack, int maxArea, int i, int height) {
        posStack.pop();
        int area = height * (i - posStack.peek() - 1);
        return area > maxArea ? area : maxArea;
    }

}

三、单调栈整体思路

单调栈主要运用在给你一个数组序列,在遍历数组时,需要向前查看元素的这种情况,此时将前面的元素入栈,形成单调栈。具体再结合题目的用意,加以利用。

整体思路还是在于自己看如何利用单调栈,有一定的难度。

其它单调栈题解:

工藤新木:柱状图中最大的矩形(单调栈)

工藤新木:每日温度(单调栈)

工藤新木:下一个更大元素 II(单调栈)

工藤新木:最大矩形(单调栈)

工藤新木:接雨水(单调栈)

工藤新木:股票价格跨度(单调栈)

工藤新木:最大宽度坡(单调栈)

如有错误,请更正指出,谢谢!

单调栈算法是一种常用的数据结构算法,主要用于处理与数组或列表相关的某些问题,特别是涉及到寻找数组中某个元素左边或右边最近的比它大或小的元素的问题。单调栈分为单调递增和单调递减。单调递增是指中的元素从底到顶保持递增的顺序,单调递减则相反。 以下是使用C语言实现单调递增的基本步骤: 1. 定义一个,并初始化一个数组来模拟的行为。 2. 遍历数组或列表中的每一个元素。 3. 对于每个元素,检查顶元素是否大于当前元素。 - 如果顶元素大于当前元素,那么将顶元素的索引从中移除,并记录当前元素是顶元素右边第一个比它小的元素。 - 重复这个过程,直到为空或者顶元素小于等于当前元素。 4. 将当前元素的索引压入中。 5. 重复步骤2-4,直到处理完所有元素。 下面是一个C语言实现单调递增的简单示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义结构体 typedef struct { int *data; int top; int capacity; } Stack; // 初始化 Stack* createStack(int capacity) { Stack *stack = (Stack*)malloc(sizeof(Stack)); stack->data = (int*)malloc(sizeof(int) * capacity); stack->capacity = capacity; stack->top = -1; return stack; } // 判断是否为空 int isEmpty(Stack *stack) { return stack->top == -1; } // 入 void push(Stack *stack, int value) { if (stack->top < stack->capacity - 1) { stack->data[++stack->top] = value; } } // 出 int pop(Stack *stack) { if (!isEmpty(stack)) { return stack->data[stack->top--]; } return -1; // 为空时返回-1 } // 获取顶元素,但不出 int peek(Stack *stack) { if (!isEmpty(stack)) { return stack->data[stack->top]; } return -1; } // 单调递增算法示例 void monotonicIncreasingStack(int *arr, int n) { Stack *stack = createStack(n); for (int i = 0; i < n; i++) { while (!isEmpty(stack) && arr[stack->top] > arr[i]) { printf("元素 %d 的右边第一个小于它的元素是 %d\n", arr[stack->top], arr[i]); pop(stack); } push(stack, i); } // 清理内存 free(stack->data); free(stack); } int main() { int arr[] = {3, 1, 2, 4}; int n = sizeof(arr) / sizeof(arr[0]); monotonicIncreasingStack(arr, n); return 0; } ``` 在这个示例中,我们使用了一个辅助函数 `monotonicIncreasingStack` 来实现单调递增算法。该函数接受一个数组和数组的长度,然后打印出每个元素右边第一个小于它的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值