学渣带你刷Leetcode0084柱状图中最大的矩形

题目描述

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

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

 

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

 

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

 

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

白话题目:
 

算法:

 

详细解释关注 B站  【C语言全代码】学渣带你刷Leetcode 不走丢 https://www.bilibili.com/video/BV1C7411y7gB

C语言完全代码

//方法二:单调栈(学习)
//1,使用数组 StackArray 模拟栈的使用
//2,如果 heights[i] > heights[i+1] 则将 栈中所有大于 heights[i+1]的 元素出栈,并计算最大面积
//3,如果 heights[i] <= heights[i+1] 则将  元素入栈
//4,最后将栈中所有元素出栈,并计算最大面积

#define     MAX_II(a, b)        ((a) > (b) ? (a) : (b))
int largestRectangleArea(int* heights, int heightsSize){
    int     i           = 0;
    int     iTop        = 0;
    int     iTmpMax     = 0;
    int     iTmpCur     = 0;
    int*    pHeight     = NULL;
    int     StackArray[heightsSize + 2];

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 2));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 2));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);

    memset(StackArray, 0x00, sizeof(int) * (heightsSize + 2));

    //1, 默认栈底 StackArray[0]=0 
    iTop = 1;

    //调换2,3的顺序,简化操作,先判断元素是否可以直接出栈计算面积,并且将栈能出栈的都出栈
    for(i = 1; i <= heightsSize + 1; i++)
    {        
        //3,出栈操作
        while(pHeight[StackArray[iTop - 1]] > pHeight[i])
        {
            iTmpCur = (i - StackArray[iTop - 2] - 1) * pHeight[StackArray[iTop - 1]];
            iTmpMax = MAX_II(iTmpCur, iTmpMax);

            iTop -= 1;
        }

        //2,入栈操作
        StackArray[iTop] = i;
        iTop += 1;
    }
    
    return iTmpMax;
}




/*
//方法一:暴力法
//1,循环遍历数组
//2,求每一个 i 对应的左边 iLeft 和右边 iRight
//3,计算每一个i对应的矩形面积,求出其中最大值

#define     MAX_III(a, b, c)    ((a) > ((b) > (c) ? (b) : (c)) ? (a) : ((b) > (c) ? (b) : (c)))
#define     MAX_II(a, b)        ((a) > (b) ? (a) : (b))
#define     MIN(a, b)           ((a) < (b) ? (a) : (b))

int largestRectangleArea(int* heights, int heightsSize){
    int     i           = 0;
    int     j           = 0;
    int     iLeft       = 0;
    int     iRight      = 0;
    int     iTmpMax     = 0;
    int     iTmpCur     = 0;
    int*    pHeight     = NULL;

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 2));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 2));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);

    for(i = 1; i <= heightsSize; i++)
    {
        //1,求左边
        for(j = i - 1; j >= 0; j--)
        
            if(pHeight[j] < pHeight[i])
            {
                iLeft = j;
                break;
            }
        }

        //2,求右边
        for(j = i + 1; j <= heightsSize + 1; j++)
        {
            if(pHeight[j] < pHeight[i])
            {
                iRight = j;
                break;
            }
        }

        //3,求面积
        iTmpCur = (iRight - iLeft - 1) * pHeight[i];
        iTmpMax = MAX_II(iTmpCur, iTmpMax);
    }

    return iTmpMax;
}
*/

/*
//方法三:动态规划算法优化
//1,如何求dp[i][j], 
//2, if(i<heights[i-1])   dp[i][j]=max(dp[i][j-1],dp[i-1][heights[i-1]], S[i][j])
//3, S[i][j]为以i,j为坐标往前找能画出的最大面积
//优化 dp[][],  dp[i][j-1],dp[i-1][heights[i-1]] 两个值都可以用临时变量代替
//解决 dp 空间问题

//优化循环处理,解决时间超时问题,j没有必要从1开始执行
//设置两个锚点,
//1,一个就是整个数组中最小值,每个 i 都需要计算一次最小j 时的面积
//2,一个就是当前j前面一个拐点,就是前面柱状图由低变高的拐点


//计算步骤:
//1,每个 i 的值都计算用 pHeight[1] 到 pHeight[i] 计算矩形面积

//问题,随着I的增加,循环次数增加,每次找左边的时间增加,导致超时
//优化,能不能把左边 k 通过每次本身的循环就固定下来

#define     MAX_III(a, b, c)    ((a) > ((b) > (c) ? (b) : (c)) ? (a) : ((b) > (c) ? (b) : (c)))
#define     MAX_II(a, b)        ((a) > (b) ? (a) : (b))
#define     MIN(a, b)           ((a) < (b) ? (a) : (b))
#define     MAXNUM              20000

int largestRectangleArea(int* heights, int heightsSize){
    int     i           = 0;
    int     j           = 0;
    int     k           = 0;
    int     iTmpS       = 0;
    int     iTmpMax     = 0;
    int     iTmpCur     = 0;
    int*    pHeight     = NULL;
    int*    pTmpK       = NULL;
    bool    bFlag       = true;

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 2));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 2));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);

    pTmpK = (int*)malloc(sizeof(int) * (heightsSize + 1));
    memset(pTmpK, 0x00, sizeof(int) * (heightsSize + 1));

    for(i = 1; i <= heightsSize; i++)
    {
        if((bFlag) && (pHeight[i] == 1))
        {
            iTmpCur += pHeight[i];
            iTmpMax = MAX_II(iTmpCur, iTmpMax);
            continue;
        }
        bFlag = false;

        //计算 pHeight[1] 到 pHeight[i] 的矩形面积
        for(j = 1; j <= i; j++)
        {
            if(pHeight[i] < pHeight[i - 1])
            {
                if(pHeight[j] > pHeight[i])
                {
                    pTmpK[j] = i;
                }
                else
                {
                    for(k = i - 1; k > 0; k--)
                    {
                        if(pHeight[k] < pHeight[j])
                        {
                            break;
                        }
                        else
                        {
                            pTmpK[k] = i;
                        }
                    }
                    pTmpK[j] = k;
                }
            }
            else
            {
                if(pHeight[j] > pHeight[i])
                {
                    pTmpK[j] = i;
                }
                pTmpK[i] = i - 1;
            }

            iTmpS = (i - pTmpK[j]) * MIN(pHeight[i], pHeight[j]);
            iTmpCur = MAX_III(iTmpCur, iTmpMax, iTmpS);
        }

        iTmpMax = MAX_II(iTmpCur, iTmpMax);
    }

    return iTmpMax;
}
*/
/*
#define     MAX_III(a, b, c)    ((a) > ((b) > (c) ? (b) : (c)) ? (a) : ((b) > (c) ? (b) : (c)))
#define     MAX_II(a, b)        ((a) > (b) ? (a) : (b))
#define     MIN(a, b)           ((a) < (b) ? (a) : (b))

int largestRectangleArea(int* heights, int heightsSize){
    int     i           = 0;
    int     j           = 0;
    int     k           = 0;
    int     iTmpS       = 0;
    int     iTmpMax     = 0;
    int     iTmpCur     = 0;
    int*    pHeight     = NULL;

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 2));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 2));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);

    for(i = 1; i <= heightsSize; i++)
    {
        //计算 pHeight[1] 到 pHeight[i] 的矩形面积
        for(j = 1; j <= i; j++)
        {
            for(k = i - 1; k > 0; k--)
            {
                if(pHeight[k] < pHeight[j])
                {
                    break;
                }
            }

            iTmpS = (i - k) * MIN(pHeight[i], pHeight[j]);
            iTmpCur = MAX_III(iTmpCur, iTmpMax, iTmpS);

//            printf("[2][i=%d][j=%d][k=%d][iTmpS=%d][iTmpCur=%d][iTmpMax=%d]\n", 
//                    i, j, k, iTmpS, iTmpCur, iTmpMax);
        }

        iTmpMax = MAX_II(iTmpCur, iTmpMax);
    }

    return iTmpMax;
}
*/


/*
//计算步骤:
//1,计算最小高度是的面积
//2,计算拐点时的面积
//3,拐点后按照 pHeight[k] 的值进行跳跃式计算


//需要记录图形中每一个拐点,每一个i 时,需要计算每个拐点的面积,
//1,首先需要计算每一个拐点的面积
//2,然后再以最后一个拐点后,按照 pHeight[k] 的值进行跳跃式计算

#define     MAX_III(a, b, c)    ((a) > ((b) > (c) ? (b) : (c)) ? (a) : ((b) > (c) ? (b) : (c)))
#define     MAX_II(a, b)        ((a) > (b) ? (a) : (b))
#define     MIN(a, b)           ((a) < (b) ? (a) : (b))

struct  TrunPoint {
    int     iTrunI;
    int     iTrunJ
};


int largestRectangleArea(int* heights, int heightsSize){
    int     i           = 0;
    int     j           = 0;
    int     k           = 0;
    int     iTmpS       = 0;
    int     iTmpMax     = 0;
    int     iTmpCur     = 0;
    int*    pHeight     = NULL;

    int     iNum        = 0;
    int     iPointNum   = 0;
    struct  TrunPoint*      pTrunPoint      = NULL;

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 2));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 2));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);

    pTrunPoint = (struct TrunPoint*)malloc(sizeof(struct TrunPoint) * (heightsSize + 1));
    memset(pTrunPoint, 0x00, sizeof(struct TrunPoint) * (heightsSize + 1));

    pTrunPoint[0].iTrunI = 0;
    pTrunPoint[0].iTrunI = 0;
    iPointNum = 1;

    for(i = 1; i <= heightsSize; i++)
    {
        if(0 == pHeight[i - 1])
        {
            iTmpCur = pHeight[i];
            iTmpMax = MAX_II(iTmpCur, iTmpMax);
            continue;
        }

        if((pHeight[i] <= pHeight[i - 1]) && (pHeight[i] < pHeight[i + 1])) 
        {
            pTrunPoint[iPointNum].iTrunI = i;
            pTrunPoint[iPointNum].iTrunJ = pHeight[i];
            iPointNum += 1;

            printf("[0][Num=%d][i=%d][j=%d]\n", iPointNum, i, pHeight[i]);
        }

        if(iPointNum > 1)
        {
            //计算所有拐点面积
            for(iNum = 1; iNum < iPointNum; iNum++)
            {
                j = pTrunPoint[iNum].iTrunJ;
                if (j <= pHeight[i])
                {
                    for(k = i - 1; k > 0; k--)
                    {
                        if(pHeight[k] < j)
                        {
                            break;
                        }
                    }

                    iTmpS = (i - k) * j;
                    iTmpCur = MAX_III(iTmpCur, iTmpMax, iTmpS);

                    printf("[1][Num=%d][iTrunI=%d][iTrunJ=%d][i=%d][j=%d][k=%d][iTmpS=%d][iTmpCur=%d][iTmpMax=%d]\n", 
                            iNum, pTrunPoint[iNum].iTrunI, pTrunPoint[iNum].iTrunJ, i, j, k, iTmpS, iTmpCur, iTmpMax);
                }
            }
        }

        //计算最后一个拐点之后的所有 i 的面积
        for(j = pTrunPoint[iPointNum - 1].iTrunJ + 1; j <= pHeight[i]; j++)
        {
            for(k = i - 1; k > 0; k--)
            {
                if(pHeight[k] < j)
                {
                    break;
                }
            }

            j = MIN(pHeight[k + 1], pHeight[i]);
            iTmpS = (i - k) * j;
            iTmpCur = MAX_III(iTmpCur, iTmpMax, iTmpS);

            printf("[2][i=%d][j=%d][k=%d][iTmpS=%d][iTmpCur=%d][iTmpMax=%d]\n", 
                    i, j, k, iTmpS, iTmpCur, iTmpMax);
        }

        iTmpMax = MAX_II(iTmpCur, iTmpMax);
    }

    return iTmpMax;
}
*/
/*
//方法二:动态规划算法优化
//1,如何求dp[i][j], 
//2, if(i<heights[i-1])   dp[i][j]=max(dp[i][j-1],dp[i-1][heights[i-1]], S[i][j])
//3, S[i][j]为以i,j为坐标往前找能画出的最大面积
//优化 dp[][],  dp[i][j-1],dp[i-1][heights[i-1]] 两个值都可以用临时变量代替
//解决 dp 空间问题
#define     MAX_III(a, b, c)    ((a) > ((b) > (c) ? (b) : (c)) ? (a) : ((b) > (c) ? (b) : (c)))
#define     MAX_II(a, b)    ((a) > (b) ? (a) : (b))
int largestRectangleArea(int* heights, int heightsSize){
    int     i           = 0;
    int     j           = 0;
    int     k           = 0;
    int     iTmpS       = 0;
    int     iTmpMax     = 0;
    int     iTmpCur     = 0;
    int*    pHeight     = NULL;

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 1));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 1));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);

    for(i = 1; i <= heightsSize; i++)
    {
        if(0 == pHeight[i - 1])
        {
            iTmpCur = pHeight[i];
            iTmpMax = MAX_II(iTmpCur, iTmpMax);
            continue;
        }
        for(j = 1; (j > 0) && (j <= pHeight[i]); j++)
        {
            for(k = i - 1; k > 0; k--)
            {
                if(pHeight[k] < j)
                {
                    break;
                }
            }

            iTmpS = (i - k) * j;
            iTmpCur = MAX_III(iTmpCur, iTmpMax, iTmpS);
        }

        iTmpMax = MAX_II(iTmpCur, iTmpMax);
    }

    return iTmpMax;
}
*/


/*
//方法一:动态规划算法
//1,如何求dp[i][j], 
//2, if(i<heights[i-1])   dp[i][j]=max(dp[i][j-1],dp[i-1][heights[i-1]], S[i][j])
//3, S[i][j]为以i,j为坐标往前找能画出的最大面积
#define     MAX(a, b, c)    ((a) > ((b) > (c) ? (b) : (c)) ? (a) : ((b) > (c) ? (b) : (c)))
int largestRectangleArea(int* heights, int heightsSize){
    int     i       = 0;
    int     j       = 0;
    int     k       = 0;
    int     iHMax   = 1000;
    int     iTmpS   = 0;
    int     iHeight = 0;
    int     dp[heightsSize + 1][iHMax];
    int*    pHeight = NULL;

    if((NULL == heights) || (0 == heightsSize)) return 0;

    pHeight = (int*)malloc(sizeof(int) * (heightsSize + 1));
    memset(pHeight, 0x00, sizeof(int) * (heightsSize + 1));
    memcpy(&pHeight[1], &heights[0], sizeof(int) * heightsSize);
    memset(dp, 0x00, sizeof(int) * (heightsSize + 1) * iHMax);

    for(i = 1; i <= heightsSize; i++)
    {
        for(j = 0; j <= pHeight[i]; j++)
        {
            if(j == 0)
            {
                dp[i][j] = dp[i - 1][pHeight[i - 1]];
                continue;
            }

            for(k = i - 1; k > 0; k--)
            {
                if(pHeight[k] < j)
                {
                    break;
                }
            }

            iTmpS = (i - k) * j;
            
            printf("[1][i=%d][j=%d][k=%d][dp[%d][%d]=%d][dp[%d][%d]=%d][iTmpS=%d]\n", 
                    i, j, k, i, j - 1, dp[i][j - 1], i - 1, pHeight[i - 1], dp[i - 1][pHeight[i - 1]], iTmpS);

            dp[i][j] = MAX(dp[i][j - 1], dp[i - 1][pHeight[i - 1]], iTmpS);
        }
    }

    return dp[heightsSize][pHeight[heightsSize]];
}
*/


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值