问题理解
题目要求计算小F在购买商品时能获得的总优惠。每件商品的价格数组p中,如果某件商品的价格p[i]大于等于前面的某个商品p[j],则小F可以享受该商品p[j]的价格作为优惠,前提是p[j]是离p[i]最近的且满足条件的商品。
数据结构选择
为了高效地找到每个商品的最近符合条件的商品,我们可以使用栈(Stack)数据结构。栈的特点是后进先出(LIFO),非常适合用来处理最近的相关问题。
算法步骤
-
初始化:创建一个栈
stack和一个变量totalDiscount来记录总优惠。 -
遍历商品:从第一个商品到最后一个商品进行遍历。
-
栈操作:
- 如果栈不为空且当前商品的价格
p[i]小于栈顶商品的价格p[stack.peek()],则弹出栈顶元素,因为当前商品不能享受栈顶商品的优惠。 - 如果栈不为空,说明栈顶商品的价格小于等于当前商品的价格,当前商品可以享受栈顶商品的价格作为优惠,将栈顶商品的价格加到
totalDiscount中。 - 将当前商品的索引入栈。
- 如果栈不为空且当前商品的价格
-
返回结果:遍历结束后,返回
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);
}
}
深度总结知识点
- 栈的应用:栈在处理最近相关问题时非常高效,如本题中的最近符合条件的商品。
- 单调栈:本题实际上是一个单调栈的应用,通过维护一个单调递减的栈,可以快速找到每个元素的最近小于等于它的元素。
- 时间复杂度:每个元素最多入栈和出栈一次,因此时间复杂度为O(N)。
- 空间复杂度:栈的空间复杂度为O(N)。
- 栈的基本操作:栈的push、pop、peek等操作是基础,需要熟练掌握。
- 单调栈的应用:单调栈是解决最近相关问题的一个常用技巧,建议多练习相关题目。
- 时间复杂度分析:在解决问题时,不仅要考虑算法的正确性,还要分析其时间复杂度和空间复杂度。
- 空间复杂度分析:栈的空间复杂度为O(N),在实际应用中需要注意空间的使用情况。
- 代码优化:在实际编码中,可以通过减少不必要的操作来优化代码,例如减少栈的弹出操作。
- 边界条件处理:在编写代码时,需要注意边界条件的处理,例如栈为空的情况。
独特理解
本题的核心在于如何高效地找到每个商品的最近符合条件的商品。通过使用栈,我们可以将这个问题转化为一个单调栈问题,从而在O(N)的时间复杂度内解决。
学习建议
- 理解栈的基本操作:栈的push、pop、peek等操作是基础,需要熟练掌握。
- 练习单调栈问题:单调栈是解决最近相关问题的一个常用技巧,建议多练习相关题目。
- 分析时间复杂度:在解决问题时,不仅要考虑算法的正确性,还要分析其时间复杂度和空间复杂度。
- 多做题:通过多做题来巩固和加深对数据结构和算法的理解。
- 代码优化:在实际编码中,可以通过减少不必要的操作来优化代码,例如减少栈的弹出操作。
- 边界条件处理:在编写代码时,需要注意边界条件的处理,例如栈为空的情况。
- 学习其他数据结构:除了栈,还有许多其他数据结构如队列、链表、树等,建议学习并掌握这些数据结构。
- 算法设计:在解决问题时,需要设计合理的算法,考虑算法的正确性、时间复杂度和空间复杂度。
- 代码调试:在编写代码时,需要注意代码的调试,通过调试来发现和解决问题。
- 代码风格:在编写代码时,需要注意代码的风格,保持代码的可读性和可维护性。