Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
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:
(i + 1)th fruit at prices[i] coins, you can get any number of the next i fruits 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:
prices[0] = 3 coins, you are allowed to take the 2nd fruit for free.prices[1] = 1 coin, you are allowed to 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:
prices[0] = 1 coin, you are allowed to take the 2nd fruit for free.prices[2] = 1 coin, you are allowed to take the 4th fruit for free.Example 3:
Input: prices = [26,18,6,12,49,7,45,45]
Output: 39
Explanation:
prices[0] = 26 coin, you are allowed to take the 2nd fruit for free.prices[2] = 6 coin, you are allowed to take the 4th, 5th and 6th (the next three) fruits for free.prices[5] = 7 coin, you are allowed to take the 8th and 9th 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] <= 105Problem summary: 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)th fruit at prices[i] coins, you can get any number of the next i fruits 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Dynamic Programming · Monotonic Queue
[3,1,2]
[1,10,1,1]
[26,18,6,12,49,7,45,45]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2944: Minimum Number of Coins for Fruits
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];
}
}
// Accepted solution for LeetCode #2944: Minimum Number of Coins for Fruits
func minimumCoins(prices []int) int {
n := len(prices)
f := make([]int, n+1)
var dfs func(int) int
dfs = func(i int) int {
if i*2 >= n {
return prices[i-1]
}
if f[i] == 0 {
f[i] = 1 << 30
for j := i + 1; j <= i*2+1; j++ {
f[i] = min(f[i], dfs(j)+prices[i-1])
}
}
return f[i]
}
return dfs(1)
}
# Accepted solution for LeetCode #2944: Minimum Number of Coins for Fruits
class Solution:
def minimumCoins(self, prices: List[int]) -> int:
@cache
def dfs(i: int) -> int:
if i * 2 >= len(prices):
return prices[i - 1]
return prices[i - 1] + min(dfs(j) for j in range(i + 1, i * 2 + 2))
return dfs(1)
// Accepted solution for LeetCode #2944: Minimum Number of Coins for Fruits
/**
* [2944] Minimum Number of Coins for Fruits
*/
pub struct Solution {}
// submission codes start here
use std::collections::VecDeque;
impl Solution {
pub fn minimum_coins(prices: Vec<i32>) -> i32 {
let n = prices.len();
// (滑动窗口的右侧, dp[i])
let mut queue = VecDeque::from([(n + 1, 0)]);
for i in (1..=n).rev() {
while queue.back().unwrap().0 > i * 2 + 1 {
queue.pop_back();
}
let dp = prices[i - 1] + queue.back().unwrap().1;
while dp <= queue.front().unwrap().1 {
queue.pop_front();
}
queue.push_front((i, dp));
}
queue.front().unwrap().1
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_2944() {
assert_eq!(4, Solution::minimum_coins(vec![3, 1, 2]));
assert_eq!(2, Solution::minimum_coins(vec![1, 10, 1, 1]));
assert_eq!(
39,
Solution::minimum_coins(vec![26, 18, 6, 12, 49, 7, 45, 45])
);
}
}
// Accepted solution for LeetCode #2944: Minimum Number of Coins for Fruits
function minimumCoins(prices: number[]): number {
const n = prices.length;
const f: number[] = Array(n + 1).fill(0);
const dfs = (i: number): number => {
if (i * 2 >= n) {
return prices[i - 1];
}
if (f[i] === 0) {
f[i] = 1 << 30;
for (let j = i + 1; j <= i * 2 + 1; ++j) {
f[i] = Math.min(f[i], prices[i - 1] + dfs(j));
}
}
return f[i];
};
return dfs(1);
}
Use this to step through a reusable interview workflow for this problem.
Pure recursion explores every possible choice at each step. With two choices per state (take or skip), the decision tree has 2ⁿ leaves. The recursion stack uses O(n) space. Many subproblems are recomputed exponentially many times.
Each cell in the DP table is computed exactly once from previously solved subproblems. The table dimensions determine both time and space. Look for the state variables — each unique combination of state values is one cell. Often a rolling array can reduce space by one dimension.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: An incomplete state merges distinct subproblems and caches incorrect answers.
Usually fails on: Correctness breaks on cases that differ only in hidden state.
Fix: Define state so each unique subproblem maps to one DP cell.