Final Prices With a Special Discount in a Shop

easy monotonic stack array

Problem

In a shop, prices[i] is the price of the i-th item. The shop runs a special offer: when you buy item i, you receive a discount equal to prices[j], where j is the first index after i whose price is less than or equal to prices[i]. If no such later item exists, you pay full price. Return the array of final prices.

This is the textbook next smaller-or-equal element pattern: each item simply waits for the first cheaper (or equally priced) item to its right, and a monotonic stack finds all of those matches in one pass.

Inputprices = [8, 4, 6, 2, 3]
Output[4, 2, 4, 2, 3]
Item 0 (8) is discounted by 4 → pays 4; item 1 (4) by 2 → pays 2; item 2 (6) by 2 → pays 4; items 3 and 4 never see a later price ≤ theirs, so they pay full price.

def final_prices(prices):
    answer = prices[:]
    stack = []                       # indices waiting for a discount
    for i, price in enumerate(prices):
        while stack and prices[stack[-1]] >= price:
            j = stack.pop()
            answer[j] = prices[j] - price
        stack.append(i)
    return answer
function finalPrices(prices) {
  const answer = prices.slice();
  const stack = []; // indices waiting for a discount
  for (let i = 0; i < prices.length; i++) {
    while (stack.length && prices[stack[stack.length - 1]] >= prices[i]) {
      const j = stack.pop();
      answer[j] = prices[j] - prices[i];
    }
    stack.push(i);
  }
  return answer;
}
int[] finalPrices(int[] prices) {
    int[] answer = prices.clone();
    Deque<Integer> stack = new ArrayDeque<>(); // waiting indices
    for (int i = 0; i < prices.length; i++) {
        while (!stack.isEmpty() && prices[stack.peek()] >= prices[i]) {
            int j = stack.pop();
            answer[j] = prices[j] - prices[i];
        }
        stack.push(i);
    }
    return answer;
}
vector<int> finalPrices(vector<int>& prices) {
    vector<int> answer = prices;
    vector<int> stack; // indices waiting for a discount
    for (int i = 0; i < (int)prices.size(); i++) {
        while (!stack.empty() && prices[stack.back()] >= prices[i]) {
            int j = stack.back(); stack.pop_back();
            answer[j] = prices[j] - prices[i];
        }
        stack.push_back(i);
    }
    return answer;
}
Time: O(n) Space: O(n)