力扣刷题动态规划篇章
力扣刷题动态规划篇章
给你一个下标从 0 开始、由 n
个整数组成的数组 nums
和一个整数 target
。
你的初始位置在下标 0
。在一步操作中,你可以从下标
i
跳跃到任意满足下述条件的下标 j
:
0 <= i < j < n
-target <= nums[j] - nums[i] <= target
返回到达下标 n - 1
处所需的
最大跳跃次数 。
如果无法到达下标 n - 1
,返回 -1
。
1 | class Solution { |
给你一个下标从 0 开始的整数数组 nums
和一个整数 target
。
返回和为 target
的 nums
子序列中,子序列
长度的最大值 。如果不存在和为 target
的子序列,返回 -1
。
子序列 指的是从原数组中删除一些或者不删除任何元素后,剩余元素保持原来的顺序构成的数组。
示例 1:
1 | 输入:nums = [1,2,3,4,5], target = 9 |
示例 2:
1 | 输入:nums = [4,1,3,2,1,5], target = 7 |
示例 3:
1 | 输入:nums = [1,1,5,4,5], target = 3 |
1 | class Solution { |
给你一个整数数组 nums
。nums
的每个元素是
1,2 或 3。在每次操作中,你可以删除 nums
中的一个元素。返回使 nums 成为 非递减 顺序所需操作数的
最小值。
示例 1:
1 | 输入:nums = [2,1,3,2,1] |
示例 2:
1 | 输入:nums = [1,3,2,1,3,3] |
示例 3:
1 | 输入:nums = [2,2,2,2,3,3] |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution {
public:
int minimumOperations(vector<int>& nums) {
vector<int> dp(3,0);
for(int i=0;i<nums.size();i++)
{
int cur=nums[i]-1;
for(int j=cur;j>=0;j--) dp[cur]=max(dp[cur],dp[j]+1);
}
int Maxn=0;
for(int i=0;i<3;i++) Maxn=max(dp[i],Maxn);
return nums.size()-Maxn;
}
};
//f(n)=max(f(1),f(2),f(n))......若n为2
给你一个下标从 0 开始的整数数组 nums
和一个正整数 x
。
你 一开始 在数组的位置 0
处,你可以按照下述规则访问数组中的其他位置:
- 如果你当前在位置
i
,那么你可以移动到满足i < j
的 任意 位置j
。 - 对于你访问的位置
i
,你可以获得分数nums[i]
。 - 如果你从位置
i
移动到位置j
且nums[i]
和nums[j]
的 奇偶性 不同,那么你将失去分数x
。
请你返回你能得到的 最大 得分之和。
注意 ,你一开始的分数为 nums[0]
。
示例 1:
1 | 输入:nums = [2,3,6,1,9,2], x = 5 |
示例 2:
1 | 输入:nums = [2,4,6,8], x = 3 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Solution {
public:
long long maxScore(vector<int>& nums, int x) {
int n = nums.size();
const long long INF = 1e18;
long long f[2];
f[0] = f[1] = -INF;
f[nums[0] % 2] = nums[0];
// 从左到右枚举访问的终点
long long ans = nums[0];
for (int i = 1; i < n; i++)
{
// 套用 dp 方程
int p = nums[i] % 2;
long long t = max(f[p] + nums[i], f[p ^ 1] + nums[i] - x);
f[p] = max(f[p], t);
ans = max(ans, t);
}
return ans;
}
};
你在一个水果超市里,货架上摆满了玲琅满目的奇珍异果。
给你一个下标从 1 开始的数组 prices
,其中 prices[i]
表示你购买第 i
个水果需要花费的金币数目。
水果超市有如下促销活动:
- 如果你花费
price[i]
购买了水果i
,那么后面的i
个水果你可以免费获得。
注意 ,即使你 可以 免费获得水果
j
,你仍然可以花费 prices[j]
个金币去购买它以便能免费获得接下来的 j
个水果。
请你返回获得所有水果所需要的 最少 金币数。
示例 1:
1 | 输入:prices = [3,1,2] |
示例 2:
1 | 输入:prices = [1,10,1,1] |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Solution {
public:
int minimumCoins(vector<int>& prices) {
int n = prices.size();
vector<int> f(n + 1, INT_MAX);
f[0] = 0;
for (int i = 1; i <= n; i++) {
/* 选择买当前水果的花费 */
int buy = f[i - 1] + prices[i - 1];
f[i] = min(f[i], buy);
/* 如果买了当前水果, 后面i个水果可以免费获得, 更新后面的最小值 */
for (int j = 1; j <= i && i + j <= n; j++) {
f[i + j] = min(f[i + j], buy);
}
}
return f[n];
}
};