当前位置: 首页 > news >正文

leetcode-单调栈26

关于单调栈的顺序总结: 

寻找右边第一个比我大的:从左到右遍历,栈单调递减
寻找左边第一个比我小的:从左到右遍历,栈单调递增
寻找右边第一个比我小的:从右到左遍历,栈单调递增
寻找左边第一个比我大的:从右到左遍历,栈单调递减

找哪边的就从哪边遍历(需要优先处理边界),找小的就单调递增(栈底小栈顶大);找大的就单调递减(栈底大栈顶小)。汉诺塔

遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。

例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出,把第二个5添加到栈中。





leetcode-739-每日温度

单调栈:当要入栈元素大于栈顶元素时,更新栈顶元素中res的值,并将栈顶元素移除

               当要入栈元素小于栈顶元素时,直接入栈

判别是否需要使用单调栈,如果需要找到左边或者右边第一个比当前位置的数大或者小,则可以考虑使用单调栈

模拟过程:

当i = 0时,单调栈为空,将0进栈

        stack = { 0(73) }

        ans = {0,0,0,0,0,0,0,0}

当i = 1时,由于74大于73,因此移除栈顶元素0,赋值ans[0] = 1-0,将1入栈

        stack = { 1(74) }

        ans = {1,0,0,0,0,0,0,0}

当i = 2时,由于75大于74,因此移除栈顶元素1,赋值ans[1] = 2-1,将2入栈

        stack = { 2(75) }

        ans = {1,1,0,0,0,0,0,0}

当i = 3时,由于71小于75,将3入栈

        stack = { 2(75),3(71) }

        ans = {1,1,0,0,0,0,0,0}

当i = 4时,由于69小于71,将4入栈

        stack = { 2(75),3(71) ,4(69)}

        ans = {1,1,0,0,0,0,0,0}

当i = 5时,由于72大于69和71,因此依次移除栈顶元素4和3,赋值ans[4] = 5-4 和 ans[3] = 5-3,将5入栈

        stack = { 2(75) ,5(72)}

        ans = {1,1,0,2,1,0,0,0}

当i = 6时,由于76大于72和75,因此依次移除栈顶元素5和2,赋值ans[5] = 6-5 和 ans[2] = 6-2,将6入栈

        stack = { 6(76) }

        ans = {1,1,0,2,1,1,0,0}

当i = 7时,由于73小于76,将7入栈

        stack = {6(76),7(73)}

        ans = {1,1,4,2,1,1,0,0}

typedef struct stkNode{
    int val;
    int index;
}stkNode;

stkNode* getNode(int val, int i){
    stkNode* node = (stkNode*)malloc(sizeof(stkNode));
    node->val = val;
    node->index = i;
    return node;
}

int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) {
    stkNode** stk = (stkNode**)malloc(sizeof(stkNode*)*temperaturesSize);
    int stk_top = 0;
    int* res = (int*)malloc(sizeof(int)*temperaturesSize);
    memset(res,0,sizeof(int)*temperaturesSize);
    for(int i = 0 ; i < temperaturesSize ; i++){
        stkNode* node = getNode(temperatures[i],i);
        while(stk_top > 0 && temperatures[i] > stk[stk_top-1]->val){
                stk_top--;
                int k = stk[stk_top]->index;
                res[k] = i-k;
        }
        stk[stk_top++] = node;
    }
    *returnSize = temperaturesSize;
    return res;
}

leetcode-496-下一个更大元素I

typedef struct stkNode {
    int val;
    int index;
}stkNode;

stkNode* getNode(int val, int index) {
    stkNode* node = (stkNode*)malloc(sizeof(stkNode));
    node->val = val;
    node->index = index;
    return node;
}

int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    stkNode* stk[1000];
    int stk_top = 0;
    int next[nums2Size];
    for(int i = 0 ; i < nums2Size ; i++){
        next[i] = 0;
    }
    for (int i = 0; i < nums2Size; i++) {
        stkNode* node = getNode(nums2[i], i);
        while (stk_top > 0 && nums2[i] > stk[stk_top - 1]->val) {
            stk_top--;
            int k = stk[stk_top]->index;
            next[k] = nums2[i];
        }
        stk[stk_top++] = node;
    }
    int* res = (int*)malloc(sizeof(int)*nums1Size);
    *returnSize = nums1Size;
    for(int i = 0 ; i < nums1Size ; i++){
        res[i] = 0;
    }
    for (int i = 0; i < nums1Size; i++) {
        for (int j = 0; j < nums2Size; j++) {
            if (nums1[i] == nums2[j]) {
                res[i] = next[j];
            }
        }
        if (res[i] == 0) {
            res[i] = -1;
        }
    }
    return res;
}

leetcode-503-下一个更大元素II

将循环数组拉直,前n-1个元素复制到数组末尾

int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize;
    if(numsSize == 0)
        return NULL;
    int* res = (int*)malloc(sizeof(int)*numsSize);
    memset(res,-1,sizeof(int)*numsSize);
    int stk[2*numsSize-1];
    int stk_top = 0;
    for(int i = 0 ; i < 2*numsSize-1 ; i++){
        while(stk_top > 0 && nums[i%numsSize] > nums[stk[stk_top-1]]){
            stk_top--;
            res[stk[stk_top]] = nums[i%numsSize];
        }
        stk[stk_top++] = i%numsSize;
    }
    return res;
}

leetcode-42-接雨水

1.双指针

列4 左侧最高的柱子是列3,高度为2。

列4 右侧最高的柱子是列7,高度为3。

列4 柱子的高度为1(以下用height表示)

那么列4的雨水高度为 列3和列7的高度最小值减列4高度,即: min(lHeight, rHeight) - height。列4的雨水高度求出来了,宽度为1,相乘就是列4的雨水体积了。

一样的方法,只要从头遍历一遍所有的列,然后求出每一列雨水的体积,相加之后就是总雨水的体积了。

首先从头遍历所有的列,并且要注意第一个柱子和最后一个柱子不接雨水

当前列雨水面积:min(左边柱子的最高高度,记录右边柱子的最高高度) - 当前柱子高度。

为了得到两边的最高高度,使用了双指针来遍历

当前位置,左边的最高高度是前一个位置的左边最高高度和本高度的最大值。

即从左向右遍历:maxLeft[i] = max(height[i], maxLeft[i - 1]);

从右向左遍历:maxRight[i] = max(height[i], maxRight[i + 1]);

int trap(int* height, int heightSize) {
    int maxLeft[heightSize];
    int maxRight[heightSize];
    maxLeft[0] = height[0];
    maxRight[heightSize-1] = height[heightSize-1];
    for(int i = 1 ; i < heightSize ; i++){
        maxLeft[i] = fmax(height[i],maxLeft[i-1]);
    }
    for(int i = heightSize-2 ; i >= 0 ; i--){
        maxRight[i] = fmax(height[i],maxRight[i+1]);
    }
    int area = 0;
    for(int i = 1 ; i < heightSize-1 ; i++){
        int high = fmin(maxLeft[i],maxRight[i])-height[i];
        area += high;
    }
    return area;
}

单调栈

int trap(int* height, int heightSize) {
    if(heightSize == 0)
        return 0;
    int ans = 0;
    int stk[heightSize];
    int top = 0;
    for(int i = 0 ; i < heightSize ; i++){
        while(top && height[i] > height[stk[top-1]]){
            int stk_top = stk[--top];
            if(!top){
                break;
            }
            int left = stk[top-1];
            int curWidth = i-left-1;
            int curHeight = fmin(height[left],height[i]) - height[stk_top];
            ans += curWidth*curHeight;
        }
        stk[top++] = i;
    }
    return ans;
}

leetcode-84-柱状图中最大的矩形

首先我们枚举某一根柱子 i 作为高 h=heights[i];

随后我们需要进行向左右两边扩展,使得扩展到的柱子的高度均不小于 h。换句话说,我们需要找到左右两侧最近的高度小于 h 的柱子,这样这两根柱子之间(不包括其本身)的所有柱子高度均不小于 h,并且就是 i 能够扩展到的最远范围。 

相关文章:

  • 开源项目介绍:GroundingDINO-TensorRT-and-ONNX-Inference
  • 2003-2016年各省互联网普及率数据
  • Ubuntu系统美化
  • 雅思练习总结(二十六)
  • defer关键字
  • RVOS-4.实现上下文切换和协作式多任务
  • 力扣每日打卡 50. Pow(x, n) (中等)
  • 玩转Docker | 使用Docker部署PDF阅读器PdfDing
  • JavaScript:BOM编程
  • 【吾爱出品】[Windows] 鼠标或键盘可自定义可同时多按键连点工具
  • 【Game】Powerful——Equipments
  • Kubernetes控制平面组件:APIServer 准入控制机制详解
  • Visual Studio Code 开发 树莓派 pico
  • 深入浅出一下Python面向对象编程的核心概念与实践应用
  • FPGA时序分析与约束(11)——时钟组
  • instructor 实现 reranker 功能
  • AtCoder Beginner Contest 401
  • Python yield关键字
  • 基于统计方法的水文数据分析及AI拓展
  • windows中搭建Ubuntu子系统
  • 上海明天短暂恢复晴热最高32℃,一大波雨水在候场
  • 解读|战国子弹库帛书漂泊海外79年今归国,追索仍将继续
  • 乌称苏梅州一公共汽车遭俄军袭击,致9死4伤
  • 女排奥运冠军宋妮娜:青少年保持身心健康才能走得更远
  • 孟夏韵评《无序的学科》丨误读与重构的文化漂流
  • 手机表面细菌菌落总数可能比马桶高10倍,医生详解如何洗手