状态转移方程中的重点
- 状态:一个数学符号,外加一个语义描述
- 决策:从所有可能产生最优解的状态中,选择一个最大值
- 阶段:本阶段只依赖上一个阶段
714. 买卖股票的最佳时机含手续费
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n = prices.size();
int dp[n][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < n; i++){
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
return max(dp[n - 1][0], dp[n - 1][1]);
}
};
213. 打家劫舍 II
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if(n == 1) return nums[0];
int dp[n][2];
dp[0][0] = 0;
dp[0][1] = nums[0];
for(int i = 1; i < n; i++){
dp[i][0] = max(dp[i - 1][1], dp[i - 1][0]);
dp[i][1] = dp[i - 1][0] + nums[i];
}
int ans1 = dp[n - 1][0];
dp[0][0] = 0;
dp[0][1] = 0;
for(int i = 1; i < n; i++){
dp[i][0] = max(dp[i - 1][1], dp[i - 1][0]);
dp[i][1] = dp[i - 1][0] + nums[i];
}
int ans2 = max(dp[n - 1][1], dp[n - 1][0]);
return max(ans1, ans2);
}
};
416. 分割等和子集
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
for(auto x : nums) sum += x;
if(sum % 2) return false;
int f[sum + 1];
memset(f, 0 , sizeof(f));
sum = 0;
f[0] = 1;
for(auto x: nums){
sum += x;
for(int j = sum; j >= x; j--){
f[j] |= f[j - x];
}
}
return f[sum / 2];
}
};
474. 一和零
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
int dp[m + 1][n + 1];
memset(dp, 0, sizeof(dp));
for(auto x : strs){
int cnt0 = 0, cnt1 = 0;
for(auto y : x){
if(y == '0') cnt0 += 1;
else cnt1 += 1;
}
for(int i = m; i >= cnt0; --i){
for(int j = n; j >= cnt1; --j){
dp[i][j] = max(dp[i][j], dp[i - cnt0][j - cnt1] + 1);
}
}
}
return dp[m][n];
}
};
518. 零钱兑换 II
class Solution {
public:
int change(int amount, vector<int>& coins) {
int f[amount + 1];
memset(f, 0, sizeof(f));
f[0] = 1;
for(auto x: coins){
for(int i = x; i <= amount; i++){
f[i] += f[i - x];
}
}
return f[amount];
}
};
377. 组合总和 Ⅳ
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
unsigned int f[target + 1];
memset(f, 0, sizeof(f));
f[0] = 1;
for(int i = 1; i <= target; i++){
for(auto x: nums){
if(i < x) continue;
f[i] += f[i - x];
}
}
return f[target];
}
};
462. 最小操作次数使数组元素相等 II
class Solution {
public:
int minMoves2(vector<int>& nums) {
int n = nums.size();
nth_element(nums.begin(), nums.begin() + n / 2, nums.end());
int x0 = nums[n / 2], ans = 0;
for(auto x: nums) ans += abs(x - x0);
return ans;
}
};
77. 组合
class Solution {
public:
void dfs(
int i, int n, int cnt, int k,
vector<int> &buff, vector<vector<int>> &ret
){
if(cnt == k){
ret.push_back(buff);
return;
}
if(n - i + 1 < k - cnt) return;
buff[cnt] = i;
dfs(i + 1, n, cnt + 1, k, buff, ret);
dfs(i + 1, n, cnt, k, buff, ret);
}
vector<vector<int>> combine(int n, int k) {
vector<int> buff(k);
vector<vector<int>> ret;
dfs(1, n, 0, k, buff, ret);
return ret;
}
};
234. 回文链表
class Solution {
public:
ListNode *reverse(ListNode *head){
ListNode ret, *p = head, *q;
while(p){
q = p->next;
p->next = ret.next;
ret.next = p;
p = q;
}
return ret.next;
}
bool isPalindrome(ListNode* head) {
if(head == nullptr) return false;
ListNode *p = head, *q = head;
while(q->next && q->next->next){
p = p->next;
q = q->next->next;
}
p->next = reverse(p->next);
q = p->next;
p = head;
while(q){
if(p->val != q->val) return false;
p = p->next;
q = q->next;
}
return true;
}
};