Closest Dessert Cost
MediumUpdated: Aug 2, 2025
Practice on:
Problem
You would like to make dessert and are preparing to buy the ingredients. You have n ice cream base flavors and m types of toppings to choose from. You must follow these rules when making your dessert:
- There must be exactly one ice cream base.
- You can add one or more types of topping or have no toppings at all.
- There are at most two of each type of topping.
You are given three inputs:
baseCosts, an integer array of lengthn, where eachbaseCosts[i]represents the price of theithice cream base flavor.toppingCosts, an integer array of lengthm, where eachtoppingCosts[i]is the price of one of theithtopping.target, an integer representing your target price for dessert.
You want to make a dessert with a total cost as close to target as possible.
Return the closest possible cost of the dessert totarget. If there are multiple, return thelower one.
Examples
Example 1
Input: baseCosts = [1,7], toppingCosts = [3,4], target = 10
Output: 10
Explanation: Consider the following combination (all 0-indexed):
- Choose base 1: cost 7
- Take 1 of topping 0: cost 1 x 3 = 3
- Take 0 of topping 1: cost 0 x 4 = 0
Total: 7 + 3 + 0 = 10.
Example 2
Input: baseCosts = [2,3], toppingCosts = [4,5,100], target = 18
Output: 17
Explanation: Consider the following combination (all 0-indexed):
- Choose base 1: cost 3
- Take 1 of topping 0: cost 1 x 4 = 4
- Take 2 of topping 1: cost 2 x 5 = 10
- Take 0 of topping 2: cost 0 x 100 = 0
Total: 3 + 4 + 10 + 0 = 17. You cannot make a dessert with a total cost of 18.
Example 3
Input: baseCosts = [3,10], toppingCosts = [2,5], target = 9
Output: 8
Explanation: It is possible to make desserts with cost 8 and 10. Return 8 as it is the lower cost.
Constraints
n == baseCosts.lengthm == toppingCosts.length1 <= n, m <= 101 <= baseCosts[i], toppingCosts[i] <= 10^41 <= target <= 10^4
Solution
Method 1 – Backtracking (DFS)
Intuition
We want to try all possible combinations of base and toppings (each topping can be used 0, 1, or 2 times) and find the cost closest to the target. Backtracking (DFS) is suitable since the number of toppings is small.
Approach
- For each base cost, use DFS to try all topping combinations (0, 1, or 2 of each topping).
- For each combination, calculate the total cost and update the answer if it's closer to the target (or smaller if equally close).
- Return the closest cost found.
Code
C++
class Solution {
public:
int ans;
void dfs(vector<int>& t, int i, int cost, int target) {
if (abs(cost - target) < abs(ans - target) || (abs(cost - target) == abs(ans - target) && cost < ans))
ans = cost;
if (i == t.size() || cost > target + abs(ans - target)) return;
dfs(t, i + 1, cost, target);
dfs(t, i + 1, cost + t[i], target);
dfs(t, i + 1, cost + 2 * t[i], target);
}
int closestCost(vector<int>& base, vector<int>& t, int target) {
ans = base[0];
for (int b : base) dfs(t, 0, b, target);
return ans;
}
};
Go
func closestCost(baseCosts, toppingCosts []int, target int) int {
ans := baseCosts[0]
var dfs func(i, cost int)
dfs = func(i, cost int) {
if abs(cost-target) < abs(ans-target) || (abs(cost-target) == abs(ans-target) && cost < ans) {
ans = cost
}
if i == len(toppingCosts) || cost > target+abs(ans-target) {
return
}
dfs(i+1, cost)
dfs(i+1, cost+toppingCosts[i])
dfs(i+1, cost+2*toppingCosts[i])
}
for _, b := range baseCosts {
dfs(0, b)
}
return ans
}
func abs(x int) int { if x < 0 { return -x }; return x }
Java
class Solution {
int ans;
public int closestCost(int[] base, int[] t, int target) {
ans = base[0];
for (int b : base) dfs(t, 0, b, target);
return ans;
}
void dfs(int[] t, int i, int cost, int target) {
if (Math.abs(cost - target) < Math.abs(ans - target) || (Math.abs(cost - target) == Math.abs(ans - target) && cost < ans))
ans = cost;
if (i == t.length || cost > target + Math.abs(ans - target)) return;
dfs(t, i + 1, cost, target);
dfs(t, i + 1, cost + t[i], target);
dfs(t, i + 1, cost + 2 * t[i], target);
}
}
Kotlin
class Solution {
var ans = 0
fun closestCost(base: IntArray, t: IntArray, target: Int): Int {
ans = base[0]
for (b in base) dfs(t, 0, b, target)
return ans
}
fun dfs(t: IntArray, i: Int, cost: Int, target: Int) {
if (kotlin.math.abs(cost - target) < kotlin.math.abs(ans - target) || (kotlin.math.abs(cost - target) == kotlin.math.abs(ans - target) && cost < ans))
ans = cost
if (i == t.size || cost > target + kotlin.math.abs(ans - target)) return
dfs(t, i + 1, cost, target)
dfs(t, i + 1, cost + t[i], target)
dfs(t, i + 1, cost + 2 * t[i], target)
}
}
Python
class Solution:
def closestCost(self, baseCosts: list[int], toppingCosts: list[int], target: int) -> int:
ans = baseCosts[0]
def dfs(i: int, cost: int):
nonlocal ans
if abs(cost - target) < abs(ans - target) or (abs(cost - target) == abs(ans - target) and cost < ans):
ans = cost
if i == len(toppingCosts) or cost > target + abs(ans - target):
return
dfs(i + 1, cost)
dfs(i + 1, cost + toppingCosts[i])
dfs(i + 1, cost + 2 * toppingCosts[i])
for b in baseCosts:
dfs(0, b)
return ans
Rust
impl Solution {
pub fn closest_cost(base: Vec<i32>, t: Vec<i32>, target: i32) -> i32 {
fn dfs(t: &Vec<i32>, i: usize, cost: i32, target: i32, ans: &mut i32) {
if (cost - target).abs() < (*ans - target).abs() || ((cost - target).abs() == (*ans - target).abs() && cost < *ans) {
*ans = cost;
}
if i == t.len() || cost > target + (*ans - target).abs() { return; }
dfs(t, i + 1, cost, target, ans);
dfs(t, i + 1, cost + t[i], target, ans);
dfs(t, i + 1, cost + 2 * t[i], target, ans);
}
let mut ans = base[0];
for &b in &base {
dfs(&t, 0, b, target, &mut ans);
}
ans
}
}
TypeScript
class Solution {
closestCost(baseCosts: number[], toppingCosts: number[], target: number): number {
let ans = baseCosts[0];
function dfs(i: number, cost: number) {
if (Math.abs(cost - target) < Math.abs(ans - target) || (Math.abs(cost - target) === Math.abs(ans - target) && cost < ans))
ans = cost;
if (i === toppingCosts.length || cost > target + Math.abs(ans - target)) return;
dfs(i + 1, cost);
dfs(i + 1, cost + toppingCosts[i]);
dfs(i + 1, cost + 2 * toppingCosts[i]);
}
for (const b of baseCosts) dfs(0, b);
return ans;
}
}
Complexity
- ⏰ Time complexity: O(3^m * n), where m is the number of toppings and n is the number of bases.
- 🧺 Space complexity: O(m), recursion stack.