zoukankan      html  css  js  c++  java
  • 1475. 商品折扣后的最终价格

    1475. 商品折扣后的最终价格

    难度简单

    给你一个数组 prices ,其中 prices[i] 是商店里第 i 件商品的价格。

    商店里正在进行促销活动,如果你要买第 i 件商品,那么你可以得到与 prices[j] 相等的折扣,其中 j 是满足 j > i 且 prices[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;
        }
    };
    主动一点,世界会更大!
  • 相关阅读:
    求字符串中最大的递增子序列
    分析函数改写自关联
    收集统计信息让SQL走正确的执行计划
    利用case when 减少表扫描次数
    利用查询提示优化SQL
    利用SQL进行推理
    查找字段连续相同的最大值
    优化有标量子查询的SQL
    将部分相同的多行记录转成一行多列
    .net 测试工具类
  • 原文地址:https://www.cnblogs.com/sweet-li/p/13564186.html
Copyright © 2011-2022 走看看