1475. 商品折扣后的最终价格(单调栈)

188 阅读1分钟

image.png

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目解析

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

二、思路分析:

我们今天拿到本题是 leetcode 难度为简单题 1475. 商品折扣后的最终价格。根据题目内容要求根据prices数组价格,按照指定的折扣规则进行计算出现相应的支付价格数组,则折扣规则为:

  • 第i件商品,满足j>i 且 prices[j] <= prices[i] 的最小索引
  • 如果不满足,则该商品则没有折扣,返回支付价格

根据题目内容,针对题目我们可以使用如下两种方法求解,思路如下:

  • 方法一:遍历求解

    • 根据题目要求第i个商品的折扣,需要从[i+1,len(prices)]范围找小于prices[i]的最小下标
    • 因此遍历prices数组时,只要找到第一个小于prices[i]的折扣即可
    • 使用for循环遍历取prices数组中每一件商品,j的坐标被赋值为i+1,进入找最小下标
    • 当prices[j]小于等于prices[i]则将prices[i]更新为prices[i]-prices[j]
    • 直到遍历完prices数组,结果返回prices
    class Solution(object):
        def finalPrices(self, prices):
            """
            :type prices: List[int]
            :rtype: List[int]
            """
            for i in range(len(prices)-1):
                j = i +1
                while j < len(prices):
                    if prices[j] <= prices[i]:
                        prices[i] = prices[i] - prices[j]
                        break
                    j +=1
            return prices
    
    
  • 方法二:单调栈

    • 栈的特点是先进后出,本题在找prices[j] <= prices[i]的最小坐标时,可以使用栈的特点来查找,那么这个栈具有单调递增的
    • 倒序遍历prices,使用栈维护右边第一个最小的元素,使得栈具有单调递增性
    • 当栈顶🆙元素大于prices[i]时,则弹出栈,直到找到st[-1]小于等于prices[i]
    • prices[i]则更新为prices[i] = p - st[-1]
    • 当st为空时,如则说明当前位置右边没有更大的元素,则prices[i]为原价
    • 并将元素i原值,添加到栈st内
    class Solution(object):
        def finalPrices(self, prices):
            """
            :type prices: List[int]
            :rtype: List[int]
            """
            n = len(prices)
            st = [0]
            for i in range(n-1,-1,-1):
                p = prices[i]
                while len(st) > 1 and st[-1] > prices[i]:
                    st.pop()
                prices[i] = p - st[-1]
                st.append(p)
            return prices
    
  • 单调栈总结

    左边、右边第一个较大、较小的数字,可以考虑用单调栈

    • 求右边第一个较大的数字:逆序遍历,单调递减栈 —— 如果当前元素大于等于栈顶元素,则栈顶出栈。
    • 求右边第一个较小的数字:逆序遍历,单调递增栈 —— 如果当前元素小于等于栈顶元素,则栈顶出栈。
    • 求左边第一个较大的数字:正序遍历,单调递减栈 —— 如果当前元素大于等于栈顶元素,则栈顶出栈。
    • 求左边第一个较小的数字:正序遍历,单调递增栈 —— 如果当前元素小于等于栈顶元素,则栈顶出栈。

三、总结:

本题对数组元素进行处理,当要指定元素的右边或者左边第一个元素值,我们可以使用单调栈来处理,对比暴力求法,可以高效处理大量数据。AC提交记录如下:

image.png

  • 时间复杂度:O(n),n为prices数组长度,一次遍历
  • 空间复杂度:O(n),栈处理需要使用额外空间

以上是本期内容,欢迎大佬们点赞评论,下期见~~~