Minimum Number of Coins for Fruits
MEDIUMDescription
You are given an 0-indexed integer array prices where prices[i] denotes the number of coins needed to purchase the (i + 1)th fruit.
The fruit market has the following reward for each fruit:
- If you purchase the
(i + 1)thfruit atprices[i]coins, you can get any number of the nextifruits for free.
Note that even if you can take fruit j for free, you can still purchase it for prices[j - 1] coins to receive its reward.
Return the minimum number of coins needed to acquire all the fruits.
Example 1:
Input: prices = [3,1,2]
Output: 4
Explanation:
- Purchase the 1st fruit with
prices[0] = 3coins, you are allowed to take the 2nd fruit for free. - Purchase the 2nd fruit with
prices[1] = 1coin, you are allowed to take the 3rd fruit for free. - Take the 3rd fruit for free.
Note that even though you could take the 2nd fruit for free as a reward of buying 1st fruit, you purchase it to receive its reward, which is more optimal.
Example 2:
Input: prices = [1,10,1,1]
Output: 2
Explanation:
- Purchase the 1st fruit with
prices[0] = 1coin, you are allowed to take the 2nd fruit for free. - Take the 2nd fruit for free.
- Purchase the 3rd fruit for
prices[2] = 1coin, you are allowed to take the 4th fruit for free. - Take the 4th fruit for free.
Example 3:
Input: prices = [26,18,6,12,49,7,45,45]
Output: 39
Explanation:
- Purchase the 1st fruit with
prices[0] = 26coin, you are allowed to take the 2nd fruit for free. - Take the 2nd fruit for free.
- Purchase the 3rd fruit for
prices[2] = 6coin, you are allowed to take the 4th, 5th and 6th (the next three) fruits for free. - Take the 4th fruit for free.
- Take the 5th fruit for free.
- Purchase the 6th fruit with
prices[5] = 7coin, you are allowed to take the 8th and 9th fruit for free. - Take the 7th fruit for free.
- Take the 8th fruit for free.
Note that even though you could take the 6th fruit for free as a reward of buying 3rd fruit, you purchase it to receive its reward, which is more optimal.
Constraints:
1 <= prices.length <= 10001 <= prices[i] <= 105
Approaches
Checkout 2 different approaches to solve Minimum Number of Coins for Fruits. Click on different approaches to view the approach and algorithm in detail.
Bottom-Up Dynamic Programming
This problem exhibits optimal substructure and overlapping subproblems, making it a good candidate for dynamic programming. We can define a DP state dp[i] as the minimum cost to acquire the first i fruits. Our goal is to find dp[n], the minimum cost for all n fruits.
The base case is dp[0] = 0, as acquiring no fruits costs nothing.
To compute dp[i], we must ensure fruit i is acquired. This can happen if we buy fruit i, or if we get it for free from a prior purchase. We can generalize this by considering that to acquire fruit i, we must have bought some fruit k (where 1 <= k <= i) that 'covers' fruit i. Buying fruit k (at index k-1) gives fruits k+1 through 2k for free. Thus, fruit k covers fruit i if k=i or k+1 <= i <= 2k. The latter condition simplifies to ceil(i/2) <= k <= i-1.
So, to find dp[i], we can take the minimum over all valid choices of k from ceil(i/2) to i. For each such k, the cost is the price of fruit k (prices[k-1]) plus the minimum cost to acquire fruits 1 to k-1 (dp[k-1]). This gives the recurrence relation:
dp[i] = min_{k=ceil(i/2)}^{i} (dp[k-1] + prices[k-1])
We can implement this by iterating i from 1 to n and, for each i, iterating k through its valid range to find the minimum cost.
Algorithm
- Create a DP array
dpof sizen+1, wherenis the number of fruits. - Initialize
dp[0] = 0, and other elements to a large value. - Iterate
ifrom 1 tonto computedp[i], the minimum cost to acquire fruits1throughi. - For each
i, calculate the cost by considering all possible fruitsk(fromceil(i/2)toi) that could be purchased to cover fruiti. - The cost of purchasing fruit
kisprices[k-1], and we must have already acquired fruits1tok-1with a minimum cost ofdp[k-1]. The total cost for this choice isdp[k-1] + prices[k-1]. - Update
dp[i]with the minimum cost found among all valid choices ofk. - The final answer is
dp[n].
We use a bottom-up dynamic programming approach. Let dp[i] be the minimum cost to obtain the first i fruits (using 1-based indexing for fruits, so i ranges from 1 to n). The size of our dp array will be n+1.
-
Initialization:
dp[0] = 0. All otherdpvalues can be initialized to infinity. -
Recurrence: To calculate
dp[i], we consider all possible fruitskwe could have purchased that would cover fruiti. A purchase of fruitkcovers fruitiifiiskitself, or ifiis one of the free fruits obtained from buyingk(i.e.,k+1 <= i <= 2k). This gives a range forkfromceil(i/2)toi. For any suchk, the total cost would be the cost to acquire fruits up tok-1(dp[k-1]) plus the cost of fruitk(prices[k-1]). We take the minimum over all these possibilities.
dp[i] = min(dp[k-1] + prices[k-1]) for k in [ceil(i/2), i]
- Final Answer: The minimum cost to acquire all
nfruits isdp[n].
Here is the Java implementation:
class Solution {
public int minimumCoins(int[] prices) {
int n = prices.length;
int[] dp = new int[n + 1];
// dp[i] = min cost to acquire first i fruits (1-based index)
dp[0] = 0;
for (int i = 1; i <= n; i++) {
dp[i] = Integer.MAX_VALUE;
// To acquire fruit i, we must buy some fruit k (1-based)
// such that buying k covers i.
// This means k=i, or k+1 <= i <= 2k.
// The range for k is [ceil(i/2), i].
// For positive integers, ceil(i/2) is (i+1)/2 using integer division.
int start_k = (i + 1) / 2;
for (int k = start_k; k <= i; k++) {
// Cost of buying fruit k is prices[k-1].
// We must have acquired fruits 1...k-1, which costs dp[k-1].
// Total cost for this choice is dp[k-1] + prices[k-1].
dp[i] = Math.min(dp[i], dp[k - 1] + prices[k - 1]);
}
}
return dp[n];
}
}
Complexity Analysis
Pros and Cons
- Relatively straightforward to understand and implement based on the DP recurrence relation.
- Correctly solves the problem for the given constraints.
- The time complexity is quadratic, which can be slow for larger constraints (though it passes for n=1000).
Code Solutions
Checking out 3 solutions in different languages for Minimum Number of Coins for Fruits. Click on different languages to view the code.
class Solution {
private
int[] prices;
private
int[] f;
private
int n;
public
int minimumCoins(int[] prices) {
n = prices.length;
f = new int[n + 1];
this.prices = prices;
return dfs(1);
}
private
int dfs(int i) {
if (i * 2 >= n) {
return prices[i - 1];
}
if (f[i] == 0) {
f[i] = 1 << 30;
for (int j = i + 1; j <= i * 2 + 1; ++j) {
f[i] = Math.min(f[i], prices[i - 1] + dfs(j));
}
}
return f[i];
}
}
Video Solution
Watch the video walkthrough for Minimum Number of Coins for Fruits
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.