1. 程式人生 > 實用技巧 >1475. 商品折扣後的最終價格

1475. 商品折扣後的最終價格

1475. 商品折扣後的最終價格

難度簡單

給你一個數組prices,其中prices[i]是商店裡第i件商品的價格。

商店裡正在進行促銷活動,如果你要買第i件商品,那麼你可以得到與prices[j]相等的折扣,其中j是滿足j > iprices[j] <= prices[i]的最小下標,如果沒有滿足條件的j,你將沒有任何折扣。

請你返回一個數組,陣列中第i個元素是折扣後你購買商品i最終需要支付的價格。

示例 1:

輸入:prices = [8,4,6,2,3]
輸出:[4,2,4,2,3]
解釋:
商品 0 的價格為 price[0]=8 ,你將得到 prices[1]=4 的折扣,所以最終價格為 8 - 4 = 4 。
商品 1 的價格為 price[1]=4 ,你將得到 prices[3]=2 的折扣,所以最終價格為 4 - 2 = 2 。
商品 2 的價格為 price[2]=6 ,你將得到 prices[3]=2 的折扣,所以最終價格為 6 - 2 = 4 。
商品 3 和 4 都沒有折扣。

示例 2:

輸入:prices = [1,2,3,4,5]
輸出:[1,2,3,4,5]
解釋:在這個例子中,所有商品都沒有折扣。

示例 3:

輸入:prices = [10,1,1,6]
輸出:[9,0,1,6]

提示:

  • 1 <= prices.length <= 500
  • 1 <= prices[i] <= 10^3

單調棧最全面詳解,包你懂!

諾*^_^*言釋出於2020-06-22867C++Java

解題思路

這裡我們考慮一個過程中的情況(這裡維護一個單調遞增的佇列,!!要將所有元素都加入一次佇列(一定記住這句話)):
>a0 a1 a2 a3 ... am ... an 單調遞增;n可以為0個(空數列,初始情況)

  1. 現在我們判斷an+1,如果an+1 <= a0 那麼a0-an的元素都需要-an+1(題幹說的第一個小於等於的元素要減去嘛;因為我們保證了a0-an是單調遞增的了(且n=1的時候就是隻有a0),所以an+1一定是第一個小於等於a0-an的),然後a0-an都出隊,因為要保持這個佇列單調遞增的性質
    此時佇列為 >an+1
  2. 繼續假設an+1,如果an+1 > a0 && an+1 <=a1,那麼a1-an的元素都需要-an+1;
    原因同第一步,此時佇列為 >a0 an+1
  3. 繼續假設an+1,如果an+1 > a1 && an+1 <=a2,那麼a2-an的元素都需要-an+1;

    原因同第一步,此時佇列為 >a0 a1 an+1
    ...
  4. 最後一種情況就是,如果an+1 > an,那麼就要將an+1加入這個單調遞增的佇列。
    此時佇列為 > a0 a1 a2 ... an an+1
    然後我們只需要迴圈上面1--4就可以了,舉個栗子給大家看看!

假設本題的序列為 8 4 9 11 5 2 6 7 9 1

初始單調遞增的序列為空a{}

1. -- 8<a0(沒有元素的時候一定入隊) --    {8}
2. -- 4<a0=8(所以a0-an出隊,並且都要減去4) --      {4}
3. -- 9>an=4(所以9入隊) --      {4 9}
4. -- 11>an=9(所以11入隊)) -- {4 9 11}
5. -- 5>a0=4 && 5<a1=9(所以9 11 出隊都減去5,然後5入隊) -- {4 5}
6. -- 2>an=5(所以4 5出隊都減去2,然後2入隊) --  {2}
7. -- 6>a0=2(所以6入隊) --     {2 6}
8. -- 7>an=6(所以7入隊) --     {2 6 7}
9. -- 9>an=7(所以9入隊)--      {2 6 7 9}
10. -- 1<a0=2(所以全部出隊都減去1,1入隊)--  {1}

******!!總結規律可以發現,我們每次比較an+1都應該從an比到a0,然後比an+1大的都出隊且減an+1,最後為
an+1找到一個合適的位置,繼續判斷an+2,這個過程由於我們需要儲存a0-an,而且比較的順序是從後往前
這不正好滿足了棧的模式麼,1記憶儲存,2從後往前,剩下的結合筆者程式碼,很容易弄懂了就。

ps:筆者也是學生,發現仔細寫個解析真的好浪費時間,真的感謝網上分享解題過程的演算法朋友們,真的辛苦了。

程式碼

c++版本

class Solution {
public:
    vector<int> finalPrices(vector<int>& prices) {
        stack<int> s;
        int len = prices.size();

        for(int i=0;i<len;i++){
            if(!s.empty() && prices[i] <= prices[s.top()]){ //為空就直接push
                while(!s.empty() && prices[i] <= prices[s.top()]){
                    int temp = s.top();
                    prices[temp] -= prices[i];
                    s.pop();
                }
            }
            s.push(i);  //儲存索引,方便再次在prices中找到這個元素
        }
        return prices;
    }
};