价格优惠计算问题 | 豆包MarsCode AI刷题

122 阅读3分钟

价格优惠计算问题

一、问题重现

问题描述

小F在“双十一”期间购买了NN件商品。每件商品有一个价格p[i]p[i],小F可以获得的优惠取决于该商品之前的一件商品。如果某一件商品的价格p[i]p[i]大于等于前面的某个商品p[j]p[j],则小F可以享受该商品p[j]p[j]的价格作为优惠,前提是p[j]p[j]是离p[i]p[i]最近的且满足条件的商品。

例如,给定价格数组p = [9, 4, 5, 2, 4],其中p[3] = 2之前没有商品的价格小于等于p[3],因此没有优惠;而p[2] = 5可以享受最近的商品p[1] = 4的价格作为优惠。因此,任务是计算小F能获得的总优惠。


测试样例

样例1:

输入:N = 5 ,p = [9, 4, 5, 2, 4]
输出:6

样例2:

输入:N = 4 ,p = [1, 2, 3, 5]
输出:6

样例3:

输入:N = 4 ,p = [4, 3, 2, 1]
输出:0

二、解题思路

  1. 初始化:定义一个栈 st 和一个队列 rep,用于存储商品价格。

  2. 遍历商品价格数组:对于每个商品价格 p[i],执行以下操作:

    • 检查栈顶元素:如果栈 st 不为空,检查栈顶元素是否大于当前商品价格 p[i]

      • 如果栈顶元素大于 p[i],则将栈顶元素移到队列 rep 中,并从栈中弹出。
      • 如果栈顶元素小于等于 p[i],则将栈顶元素累加到结果 ans 中,并退出循环。
    • 恢复栈状态:将队列 rep 中的元素重新压入栈 st 中。

    • 压入当前商品价格:将当前商品价格 p[i] 压入栈 st 中。

  3. 返回结果:返回累加的结果 ans

关键点

  1. 栈和队列的使用:栈 st 用于存储商品价格,队列 rep 用于临时存储需要重新压入栈的元素。
  2. 检查栈顶元素:在遍历过程中,检查栈顶元素是否大于当前商品价格 p[i],如果是,则将栈顶元素移到队列 rep 中。
  3. 恢复栈状态:在每次遍历结束后,将队列 rep 中的元素重新压入栈 st 中,以恢复栈的状态。
  4. 累加优惠:如果栈顶元素小于等于当前商品价格 p[i],则将其累加到结果 ans 中。

三、代码实现

int solution(int N, std::vector<int>& p) {

    int ans = 0;

    stack<int> st;

    queue<int> rep;

    for(int i = 0; i < N; ++i) {

        while(!st.empty()) {

            if(st.top() > p[i]) {

                rep.push(st.top());

                st.pop();

            }

            else {

                ans += st.top();

                break;

            }

        }

        while (!rep.empty()) {

            st.push(rep.front());

            rep.pop();

        }

       

        st.push(p[i]);

    }

    return ans;

}

四、算法复杂度分析

时间复杂度

  1. 外层循环:外层循环遍历商品价格数组 p,时间复杂度为 O(N)

  2. 内层循环

    • 第一个 while 循环:在每次外层循环中,第一个 while 循环会遍历栈 st,直到找到一个满足条件的栈顶元素或栈为空。在最坏情况下,每次外层循环都会遍历整个栈,但由于栈的大小不会超过 N,因此这个循环的总时间复杂度为 O(N)
    • 第二个 while 循环:在每次外层循环中,第二个 while 循环会将队列 rep 中的元素重新压入栈 st。在最坏情况下,每次外层循环都会遍历整个队列,但由于队列的大小不会超过 N,因此这个循环的总时间复杂度为 O(N)

空间复杂度

  1. 栈 st:栈 st 的最大大小为 N,因此空间复杂度为 O(N)
  2. 队列 rep:队列 rep 的最大大小为 N,因此空间复杂度为 O(N)