Maximum Ice Cream Bars
Problem
It is a sweltering summer day, and a boy wants to buy some ice cream bars.
At the store, there are n ice cream bars. You are given an array costs of length n, where costs[i] is the price of the ith ice cream bar in coins.
The boy initially has coins coins to spend, and he wants to buy as many ice cream bars as possible.
Note: The boy can buy the ice cream bars in any order.
Return _themaximum number of ice cream bars the boy can buy with _coins
coins.
You must solve the problem by counting sort.
Examples
Example 1
Input: costs = [1,3,2,4,1], coins = 7
Output: 4
Explanation: The boy can buy ice cream bars at indices 0,1,2,4 for a total price of 1 + 3 + 2 + 1 = 7.
Example 2
Input: costs = [10,6,8,7,7,8], coins = 5
Output: 0
Explanation: The boy cannot afford any of the ice cream bars.
Example 3
Input: costs = [1,6,3,1,2,5], coins = 20
Output: 6
Explanation: The boy can buy all the ice cream bars for a total price of 1 + 6 + 3 + 1 + 2 + 5 = 18.
Constraints
costs.length == n1 <= n <= 10^51 <= costs[i] <= 10^51 <= coins <= 10^8
Solution
Method 1 – Counting Sort Greedy
Intuition
To maximize the number of ice cream bars, always buy the cheapest bars first. Since costs are bounded, we can use counting sort to efficiently count the number of bars at each price, then buy as many as possible from cheapest to most expensive until coins run out.
Approach
- Find the maximum cost in the array to determine the counting sort range.
- Create a count array where count[i] is the number of bars costing i coins.
- For each price from lowest to highest:
- Buy as many bars as possible at that price, without exceeding the available coins.
- Subtract the total cost from coins and add the number of bars bought to the answer.
- Stop if coins run out.
- Return the total number of bars bought.
Code
C++
class Solution {
public:
int maxIceCream(vector<int>& costs, int coins) {
int mx = *max_element(costs.begin(), costs.end());
vector<int> cnt(mx + 1);
for (int c : costs) cnt[c]++;
int ans = 0;
for (int i = 1; i <= mx && coins > 0; ++i) {
int buy = min(cnt[i], coins / i);
ans += buy;
coins -= buy * i;
}
return ans;
}
};
Go
func maxIceCream(costs []int, coins int) int {
mx := 0
for _, c := range costs {
if c > mx {
mx = c
}
}
cnt := make([]int, mx+1)
for _, c := range costs {
cnt[c]++
}
ans := 0
for i := 1; i <= mx && coins > 0; i++ {
buy := cnt[i]
if buy > coins/i {
buy = coins / i
}
ans += buy
coins -= buy * i
}
return ans
}
Java
class Solution {
public int maxIceCream(int[] costs, int coins) {
int mx = 0;
for (int c : costs) mx = Math.max(mx, c);
int[] cnt = new int[mx + 1];
for (int c : costs) cnt[c]++;
int ans = 0;
for (int i = 1; i <= mx && coins > 0; ++i) {
int buy = Math.min(cnt[i], coins / i);
ans += buy;
coins -= buy * i;
}
return ans;
}
}
Kotlin
class Solution {
fun maxIceCream(costs: IntArray, coins: Int): Int {
var mx = 0
for (c in costs) mx = maxOf(mx, c)
val cnt = IntArray(mx + 1)
for (c in costs) cnt[c]++
var ans = 0
var coinsLeft = coins
for (i in 1..mx) {
if (coinsLeft <= 0) break
val buy = minOf(cnt[i], coinsLeft / i)
ans += buy
coinsLeft -= buy * i
}
return ans
}
}
Python
class Solution:
def maxIceCream(self, costs: list[int], coins: int) -> int:
mx = max(costs)
cnt = [0] * (mx + 1)
for c in costs:
cnt[c] += 1
ans = 0
for i in range(1, mx + 1):
if coins <= 0:
break
buy = min(cnt[i], coins // i)
ans += buy
coins -= buy * i
return ans
Rust
impl Solution {
pub fn max_ice_cream(costs: Vec<i32>, coins: i32) -> i32 {
let mx = *costs.iter().max().unwrap();
let mut cnt = vec![0; (mx + 1) as usize];
for &c in &costs {
cnt[c as usize] += 1;
}
let mut ans = 0;
let mut coins = coins;
for i in 1..=mx {
let buy = cnt[i as usize].min(coins / i);
ans += buy;
coins -= buy * i;
if coins <= 0 { break; }
}
ans
}
}
TypeScript
class Solution {
maxIceCream(costs: number[], coins: number): number {
const mx = Math.max(...costs);
const cnt = Array(mx + 1).fill(0);
for (const c of costs) cnt[c]++;
let ans = 0;
for (let i = 1; i <= mx && coins > 0; ++i) {
const buy = Math.min(cnt[i], Math.floor(coins / i));
ans += buy;
coins -= buy * i;
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n + C), where n is the number of bars and C is the maximum cost. Counting sort and the greedy loop are both linear. - 🧺 Space complexity:
O(C), for the counting array.