Buy Maximum Stocks if i Stocks Buyable on Day i is a clean greedy problem. It teaches a core habit: when you want the most items for a fixed budget, spend on the cheapest first.
Problem. You have a list of stock price values. On day i (1-indexed) you are allowed to buy at
most i shares of that day's stock. With a total budget, buy the maximum number of shares you can.
Example: price = [10, 7, 19] on days 1, 2, 3 (so day_limit = [1, 2, 3]), budget = 45.
Best answer: 4 shares (2 of price 7, 1 of price 10, 1 of price 19).
The slow way first
You might try every combination of how many shares to take from each day and keep the best total within budget. With many days that explodes combinatorially — far too slow, and there is no obvious recurrence to memoize cleanly.
The question to ask: to maximize the share count, which dollar should I spend next? The dollar that buys the most shares — that is, the one spent on the cheapest stock. That hint points straight at a greedy strategy.
The idea: cheapest price first
Pair each price with its day limit, then sort the pairs by price. Walk the sorted list cheapest-first. For each stock, buy as many shares as you can afford and the day limit allows: qty = min(limit, budget // price). Subtract the cost, add to the running count, and move to the next-cheapest stock.
Why is greedy correct? Spending a dollar on a cheaper share always yields at least as many shares as spending it on a costlier one, and the day limit only caps each stock independently. So exhausting the cheapest first can never be beaten.
Walk through it
Step through the animation. The pairs are already sorted by price: 7, 10, 19 with limits 2, 1, 3. The buy pointer moves cheapest-to-costliest. At each stock we take min(limit, budget // price) shares, watch the budget shrink, and watch the bought count climb to 4.
Pseudocode
pair each price with its day limit
sort the pairs by price (cheapest first)
bought = 0
for each (price, limit) in the sorted pairs:
qty = min(limit, budget // price) # afford-able and allowed
bought = bought + qty
budget = budget - qty * price # pay for them
return boughtThe Python solution
def max_stocks(price, day_limit, budget):
stocks = list(zip(price, day_limit))
stocks.sort()
bought = 0
for p, limit in stocks:
qty = min(limit, budget // p)
bought += qty
budget -= qty * p
return boughtzip(price, day_limit)builds the(price, limit)pairs; sorting a list of tuples sorts by the first field, the price.boughtaccumulates the total number of shares.qty = min(limit, budget // p)is the heart of the greedy step:budget // pis how many we can afford,limitis how many we are allowed that day, and we take the smaller.budget -= qty * ppays for those shares so later stocks see the reduced budget.- We return
boughtonce every pair has been considered.
Complexity
| Case | Time | Notes |
|---|---|---|
| Sorting the pairs | O(n log n) (moderate) | dominates the runtime |
| Greedy sweep | O(n) (moderate) | one pass, O(1) work each |
O(n) (moderate)The sort is the bottleneck at O(n log n); the buying sweep is a single linear pass. The extra O(n) space holds the paired list.
When this pattern shows up
When a problem asks for the maximum count of items under a fixed budget or capacity, sort by cost and take the cheapest first. The same greedy move powers "maximum events you can attend," fractional knapsack, and many resource-allocation questions.
Do not forget the per-day cap. Even when you can afford more, the day limit i bounds how many shares
of that stock you may buy, so the quantity is always min(limit, budget // price), never just budget // price.
Practice
After buying 2 shares at price 7 (budget now 31), you reach price 10 with day limit 1. How many shares do you buy?
1. In what order does the greedy algorithm consider the stocks?
2. Why is the quantity min(limit, budget // price) rather than just budget // price?
3. What dominates the time complexity?
4. For price = [10, 7, 19], day_limit = [1, 2, 3], budget = 45, how many shares can you buy?