“价格优惠计算问题”题目要求
一、问题描述
小F在“双十一”期间购买了 件商品。每件商品有一个价格 ,小F 可以获得的优惠取决于该商品之前的一件商品。如果某一件商品的价格 大于等于前面的某个商品 ,则小F 可以享受该商品 的价格作为优惠,前提是 是离 最近的且满足条件的商品。
例如,给定价格数组 ,其中 之前没有商品的价格小于等于 ,因此没有优惠;而 可以享受最近的商品 的价格作为优惠。因此,任务是计算小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代码思路
- 遍历数组:我们需要遍历价格数组
p,对于每个商品p[i],我们需要检查它之前的所有商品p[j](其中j < i)。 - 查找最近的符合条件的商品:对于每个商品
p[i],我们需要找到它之前最近的商品p[j],使得p[j] <= p[i]。 - 计算优惠:如果找到了符合条件的商品
p[j],则优惠金额为p[j],将其累加到总优惠中。 - 返回总优惠:最后返回累加的总优惠金额。
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改进而成。比原代码具有更好的效果。这段代码的核心编程思想体现在以下几个方面:
- 最近更小值问题的优化:在原始解法中,通过双层循环从后向前查找符合条件的商品,导致时间复杂度较高(O(N^2))。优化后的代码引入了栈(Stack)来实现「最近更小值」的查询,将复杂度降至 O(N)。
- 栈的单调性维护:在处理数组中的每个元素时,利用栈来维护一个单调不增(非严格递减)的顺序,使得栈中的元素总是当前索引之前的、价格小于或等于当前商品价格的索引。这样在栈顶的索引即为当前商品的最近满足条件的商品,从而避免重复查找。
- 代码效率优化:利用栈结构在遍历时仅需 O(N) 时间复杂度。这种优化思路非常适合在查找「最近更小/大」类型的题目中应用,避免了双层循环的重复计算,极大提高了代码的性能。
- 灵活利用栈的LIFO特性:栈作为一种后进先出的数据结构,在本算法中特别适用于「最近」这一特性问题的处理。通过维护栈顶元素,可以快速找到符合条件的最近索引位置,使得我们可以高效地计算出每个商品的优惠值。