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

116 阅读4分钟

问题理解

题目要求计算小F在购买商品时能获得的总优惠。每件商品的价格数组p中,如果某件商品的价格p[i]大于等于前面的某个商品p[j],则小F可以享受该商品p[j]的价格作为优惠,前提是p[j]是离p[i]最近的且满足条件的商品。

数据结构选择

为了高效地找到每个商品的最近符合条件的商品,我们可以使用栈(Stack)数据结构。栈的特点是后进先出(LIFO),非常适合用来处理最近的相关问题。

算法步骤

  1. 初始化:创建一个栈stack和一个变量totalDiscount来记录总优惠。

  2. 遍历商品:从第一个商品到最后一个商品进行遍历。

  3. 栈操作

    • 如果栈不为空且当前商品的价格p[i]小于栈顶商品的价格p[stack.peek()],则弹出栈顶元素,因为当前商品不能享受栈顶商品的优惠。
    • 如果栈不为空,说明栈顶商品的价格小于等于当前商品的价格,当前商品可以享受栈顶商品的价格作为优惠,将栈顶商品的价格加到totalDiscount中。
    • 将当前商品的索引入栈。
  4. 返回结果:遍历结束后,返回totalDiscount

代码详解

import java.util.Stack;

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

    for (int i = 0; i < N; i++) {
        // 处理当前商品的价格 p[i]
        while (!stack.isEmpty() && p[stack.peek()] > p[i]) {
            stack.pop(); // 弹出不符合条件的商品
        }
        // 如果栈不为空,说明有符合条件的商品
        if (!stack.isEmpty()) {
            totalDiscount += p[stack.peek()]; // 添加最近符合条件的商品的价格
        }
        // 将当前商品的索引入栈
        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);
}

}

深度总结知识点

  1. 栈的应用:栈在处理最近相关问题时非常高效,如本题中的最近符合条件的商品。
  2. 单调栈:本题实际上是一个单调栈的应用,通过维护一个单调递减的栈,可以快速找到每个元素的最近小于等于它的元素。
  3. 时间复杂度:每个元素最多入栈和出栈一次,因此时间复杂度为O(N)。
  4. 空间复杂度:栈的空间复杂度为O(N)。
  5. 栈的基本操作:栈的push、pop、peek等操作是基础,需要熟练掌握。
  6. 单调栈的应用:单调栈是解决最近相关问题的一个常用技巧,建议多练习相关题目。
  7. 时间复杂度分析:在解决问题时,不仅要考虑算法的正确性,还要分析其时间复杂度和空间复杂度。
  8. 空间复杂度分析:栈的空间复杂度为O(N),在实际应用中需要注意空间的使用情况。
  9. 代码优化:在实际编码中,可以通过减少不必要的操作来优化代码,例如减少栈的弹出操作。
  10. 边界条件处理:在编写代码时,需要注意边界条件的处理,例如栈为空的情况。

独特理解

本题的核心在于如何高效地找到每个商品的最近符合条件的商品。通过使用栈,我们可以将这个问题转化为一个单调栈问题,从而在O(N)的时间复杂度内解决。

学习建议

  1. 理解栈的基本操作:栈的push、pop、peek等操作是基础,需要熟练掌握。
  2. 练习单调栈问题:单调栈是解决最近相关问题的一个常用技巧,建议多练习相关题目。
  3. 分析时间复杂度:在解决问题时,不仅要考虑算法的正确性,还要分析其时间复杂度和空间复杂度。
  4. 多做题:通过多做题来巩固和加深对数据结构和算法的理解。
  5. 代码优化:在实际编码中,可以通过减少不必要的操作来优化代码,例如减少栈的弹出操作。
  6. 边界条件处理:在编写代码时,需要注意边界条件的处理,例如栈为空的情况。
  7. 学习其他数据结构:除了栈,还有许多其他数据结构如队列、链表、树等,建议学习并掌握这些数据结构。
  8. 算法设计:在解决问题时,需要设计合理的算法,考虑算法的正确性、时间复杂度和空间复杂度。
  9. 代码调试:在编写代码时,需要注意代码的调试,通过调试来发现和解决问题。
  10. 代码风格:在编写代码时,需要注意代码的风格,保持代码的可读性和可维护性。