You are given an integer array prices
where prices[i]
is the price of the ith
item in a shop.
There is a special discount for items in the shop. If you buy the ith
item, then you will receive a discount equivalent to prices[j]
where j
is the minimum index such that j > i
and prices[j] <= prices[i]
. Otherwise, you will not receive any discount at all.
Return an integer array answer
where answer[i]
is the final price you will pay for the ith
item of the shop, considering the special discount.
Example 1:
Input: prices = [8,4,6,2,3] Output: [4,2,4,2,3] Explanation: For item 0 with price[0]=8 you will receive a discount equivalent to prices[1]=4, therefore, the final price you will pay is 8 - 4 = 4. For item 1 with price[1]=4 you will receive a discount equivalent to prices[3]=2, therefore, the final price you will pay is 4 - 2 = 2. For item 2 with price[2]=6 you will receive a discount equivalent to prices[3]=2, therefore, the final price you will pay is 6 - 2 = 4. For items 3 and 4 you will not receive any discount at all.
Example 2:
Input: prices = [1,2,3,4,5] Output: [1,2,3,4,5] Explanation: In this case, for all items, you will not receive any discount at all.
Example 3:
Input: prices = [10,1,1,6] Output: [9,0,1,6]
Constraints:
1 <= prices.length <= 500
1 <= prices[i] <= 1000
This problem asks to calculate the final price of each item after applying a special discount. The discount for the i
th item is the price of the first item with a lower price found at an index greater than i
. A monotonic stack provides an efficient solution.
Approach:
We iterate through the prices
array from right to left. A monotonic decreasing stack is used to store the prices encountered so far. For each price, we check the stack:
Pop from Stack: As long as the stack is not empty and the top of the stack (representing a previously encountered price) is greater than the current price, we pop elements from the stack. This is because those popped prices will never be a valid discount for any future item (since the current price is smaller and comes later).
Apply Discount (if applicable): If the stack is not empty after popping, the top of the stack is the nearest smaller price to the right. We subtract this top price from the current price to apply the discount.
Push onto Stack: Finally, the current price is pushed onto the stack to maintain the decreasing order.
Time Complexity: O(n) - Each element is pushed and popped at most once from the stack. The iteration through the array is linear.
Space Complexity: O(n) - In the worst-case scenario, the stack could potentially store all elements of the prices
array.
The core logic remains the same across all languages: iterate in reverse order, use a stack to maintain decreasing prices, pop greater elements, apply discount if a smaller element is found, and push the current element. Here's the detailed code in multiple languages:
Python:
def finalPrices(prices):
stack = []
for i in range(len(prices) - 1, -1, -1):
price = prices[i]
while stack and stack[-1] > price:
stack.pop()
discount = stack[-1] if stack else 0
prices[i] -= discount
stack.append(price)
return prices
Java:
import java.util.Deque;
import java.util.ArrayDeque;
class Solution {
public int[] finalPrices(int[] prices) {
Deque<Integer> stack = new ArrayDeque<>();
for (int i = prices.length - 1; i >= 0; i--) {
int price = prices[i];
while (!stack.isEmpty() && stack.peek() > price) {
stack.pop();
}
int discount = stack.isEmpty() ? 0 : stack.peek();
prices[i] -= discount;
stack.push(price);
}
return prices;
}
}
C++:
#include <vector>
#include <stack>
class Solution {
public:
std::vector<int> finalPrices(std::vector<int>& prices) {
std::stack<int> stack;
for (int i = prices.size() - 1; i >= 0; i--) {
int price = prices[i];
while (!stack.empty() && stack.top() > price) {
stack.pop();
}
int discount = stack.empty() ? 0 : stack.top();
prices[i] -= discount;
stack.push(price);
}
return prices;
}
};
JavaScript:
var finalPrices = function(prices) {
let stack = [];
for (let i = prices.length - 1; i >= 0; i--) {
let price = prices[i];
while (stack.length > 0 && stack[stack.length - 1] > price) {
stack.pop();
}
let discount = stack.length === 0 ? 0 : stack[stack.length - 1];
prices[i] -= discount;
stack.push(price);
}
return prices;
};
//Other languages like Go, TypeScript, Rust, and PHP would follow similar structures, using their respective stack implementations. The core algorithm remains consistent.