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

105 阅读3分钟

“价格优惠计算问题”题目要求

一、问题描述

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

例如,给定价格数组 p=[9,4,5,2,4]p = [9, 4, 5, 2, 4],其中 p[3]=2p[3] = 2 之前没有商品的价格小于等于 p[3]p[3],因此没有优惠;而 p[2]=5p[2] = 5 可以享受最近的商品 p[1]=4p[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


三、题目解析

3.1代码思路

  1. 遍历数组:我们需要遍历价格数组 p,对于每个商品 p[i],我们需要检查它之前的所有商品 p[j](其中 j < i)。
  2. 查找最近的符合条件的商品:对于每个商品 p[i],我们需要找到它之前最近的商品 p[j],使得 p[j] <= p[i]
  3. 计算优惠:如果找到了符合条件的商品 p[j],则优惠金额为 p[j],将其累加到总优惠中。
  4. 返回总优惠:最后返回累加的总优惠金额。

3.2详细代码

原始代码

public class Main {
    public static int solution(int N, int[] p) {
        int totalDiscount = 0;
        
        // 遍历每个商品
        for (int i = 1; i < N; i++) {
            // 查找最近的符合条件的商品
            for (int j = i - 1; j >= 0; j--) {
                if (p[j] <= p[i]) {
                    // 找到符合条件的商品,累加优惠
                    totalDiscount += p[j];
                    break; // 找到最近的符合条件的商品后跳出内层循环
                }
            }
        }
        
        return totalDiscount;
    }

    public static void main(String[] args) {
        System.out.println(solution(5, new int[]{9, 4, 5, 2, 4}) == 6);
        System.out.println(solution(4, new int[]{1, 2, 3, 5}) == 6);
        System.out.println(solution(4, new int[]{4, 3, 2, 1}) == 0);
    }
}

改进代码

import java.util.Stack;

public class Main {
    public static int solution(int N, int[] p) {
        int totalDiscount = 0;
        Stack<Integer> stack = new Stack<>();

        for (int i = 0; i < N; i++) {
            // Pop elements from stack while they are greater than current price
            while (!stack.isEmpty() && p[stack.peek()] > p[i]) {
                stack.pop();
            }

            // If stack is not empty, top of the stack is the nearest smaller or equal price
            if (!stack.isEmpty()) {
                totalDiscount += p[stack.peek()];
            }

            // Push current index onto the stack
            stack.push(i);
        }

        return totalDiscount;
    }

    public static void main(String[] args) {
        System.out.println(solution(5, new int[]{9, 4, 5, 2, 4}) == 6);
        System.out.println(solution(4, new int[]{1, 2, 3, 5}) == 6);
        System.out.println(solution(4, new int[]{4, 3, 2, 1}) == 0);
    }
}



四、知识总结

改进代码是利用MarsCode AI改进而成。比原代码具有更好的效果。这段代码的核心编程思想体现在以下几个方面:

  1. 最近更小值问题的优化:在原始解法中,通过双层循环从后向前查找符合条件的商品,导致时间复杂度较高(O(N^2))。优化后的代码引入了栈(Stack)来实现「最近更小值」的查询,将复杂度降至 O(N)。
  2. 栈的单调性维护:在处理数组中的每个元素时,利用栈来维护一个单调不增(非严格递减)的顺序,使得栈中的元素总是当前索引之前的、价格小于或等于当前商品价格的索引。这样在栈顶的索引即为当前商品的最近满足条件的商品,从而避免重复查找。
  3. 代码效率优化:利用栈结构在遍历时仅需 O(N) 时间复杂度。这种优化思路非常适合在查找「最近更小/大」类型的题目中应用,避免了双层循环的重复计算,极大提高了代码的性能。
  4. 灵活利用栈的LIFO特性:栈作为一种后进先出的数据结构,在本算法中特别适用于「最近」这一特性问题的处理。通过维护栈顶元素,可以快速找到符合条件的最近索引位置,使得我们可以高效地计算出每个商品的优惠值。