力扣2944.购买水果需要的最少金币数
- 先想到递归,逐步优化
- 递归 –> 记忆化搜索 –> 递推 –> 单调队列优化
记忆化搜索dfs
-
class Solution { public: int minimumCoins(vector<int>& prices) { int n = prices.size(); //记忆化搜索数组 vector<int> memo((n+1) / 2); function<int(int)> dfs = [&](int i) -> int { //边界 后面的水果直接全部获取到 if(i * 2 >= n) return prices[i-1]; int &res = memo[i]; //之前出现过 直接return if(res) return res; res = INT_MAX; //[i+1,2i+1]递归 for(int j=i+1;j<=i*2+1;j++) res = min(res,dfs(j)); //把当前的金币加上 res += prices[i-1]; return res; }; return dfs(1); } };
递推
-
倒序从**(n+1)/2-1**遍历i
- price[i-1] += min(price[i],price[i+1]…….price[i*2])
-
class Solution { public: int minimumCoins(vector<int>& prices) { int n = prices.size(); for(int i=(n+1)/2 - 1;i>0;i--) //min_element函数传入参数为[st,ed) prices[i-1] += *min_element(prices.begin() + i,prices.begin() + i*2 +1); return prices[0]; } };
单调队列优化
-
队首在左边,队尾在右边
-
class Solution { public: int minimumCoins(vector<int>& prices) { int n = prices.size(); deque<pair<int,int>> q; //哨兵 q.emplace_front(n+1,0); for(int i=n;i>0;i--) { while(q.back().first > i * 2 + 1) q.pop_back(); //当哨兵还在队列中时 q.back().second 始终为0 int f = prices[i-1] + q.back().second; //second存 获得它及以后所有的水果的最小值 while(f <= q.front().second) q.pop_front(); q.emplace_front(i,f); } return q.front().second; } };