The Leetcode problem "Apply Discount Every n Orders" asks you to design a system for a restaurant that applies a discount to every n
th order. You are given three parameters:
n
: Every n
th customer gets a discount.discount
: The percentage discount to apply (e.g. 20 for 20%).products
and prices
: Lists of product IDs and their corresponding prices.
You must implement a class so that when getBill(product, amount)
is called, it returns the total bill for the customer, applying the discount if this is the n
th customer. Each call to getBill
represents a new order. Key constraints include:
At first glance, the problem might look like a simple calculation of totals and discounts. However, the challenge is in tracking the number of orders to ensure the discount is applied only on every n
th order. We need to:
n
.A brute-force approach would be to keep a list of all orders, but this is unnecessary and inefficient. Instead, we can optimize by using a simple counter and a dictionary for price lookups.
The solution can be broken down into the following steps:
n
and discount
as class variables.getBill
is called, increment the order counter.n
, apply the discount to the total.
Suppose n = 3
, discount = 20
, products = [1,2,3]
, prices = [100,200,300]
.
getBill([1,2], [1,2])
getBill([3], [2])
getBill([1,3], [3,1])
getBill([2], [1])
This pattern repeats, with every 3rd order receiving the discount.
getBill
call, where m is the number of products in the order (since we sum over each product).The key to solving "Apply Discount Every n Orders" efficiently is to use a counter to track orders and a dictionary for quick price lookups. This avoids unnecessary storage and ensures that the discount logic is simple and reliable. The approach is both efficient and easy to maintain, making it an elegant solution to the problem.
class Cashier:
def __init__(self, n: int, discount: int, products: List[int], prices: List[int]):
self.n = n
self.discount = discount
self.count = 0
self.price_map = {pid: price for pid, price in zip(products, prices)}
def getBill(self, product: List[int], amount: List[int]) -> float:
self.count += 1
total = 0
for pid, amt in zip(product, amount):
total += self.price_map[pid] * amt
if self.count % self.n == 0:
total = total * (100 - self.discount) / 100
return total
class Cashier {
public:
int n, discount, count;
unordered_map<int, int> price_map;
Cashier(int n, int discount, vector<int>& products, vector<int>& prices) {
this->n = n;
this->discount = discount;
count = 0;
for (int i = 0; i < products.size(); ++i)
price_map[products[i]] = prices[i];
}
double getBill(vector<int>& product, vector<int>& amount) {
count++;
double total = 0;
for (int i = 0; i < product.size(); ++i)
total += price_map[product[i]] * amount[i];
if (count % n == 0)
total = total * (100 - discount) / 100.0;
return total;
}
};
class Cashier {
int n, discount, count;
Map<Integer, Integer> priceMap;
public Cashier(int n, int discount, int[] products, int[] prices) {
this.n = n;
this.discount = discount;
this.count = 0;
priceMap = new HashMap<>();
for (int i = 0; i < products.length; ++i) {
priceMap.put(products[i], prices[i]);
}
}
public double getBill(int[] product, int[] amount) {
count++;
double total = 0;
for (int i = 0; i < product.length; ++i) {
total += priceMap.get(product[i]) * amount[i];
}
if (count % n == 0) {
total = total * (100 - discount) / 100.0;
}
return total;
}
}
var Cashier = function(n, discount, products, prices) {
this.n = n;
this.discount = discount;
this.count = 0;
this.priceMap = {};
for (let i = 0; i < products.length; ++i) {
this.priceMap[products[i]] = prices[i];
}
};
Cashier.prototype.getBill = function(product, amount) {
this.count += 1;
let total = 0;
for (let i = 0; i < product.length; ++i) {
total += this.priceMap[product[i]] * amount[i];
}
if (this.count % this.n === 0) {
total = total * (100 - this.discount) / 100;
}
return total;
};