學渣帶你刷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]];
}
*/


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章