经典线性dp
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
for(int i = 1; i < n; i++) { //处理边界,以防stack overflow
triangle[i][0] += triangle[i-1][0];
triangle[i][i] += triangle[i-1][i-1];
}
for(int i = 2; i < n; i++)
for(int j = 1; j < i; j++)
triangle[i][j] += min(triangle[i-1][j],triangle[i-1][j-1]);
int res = 0x3f3f3f3f;
for(int i = 0; i < n; i++) res = min(res,triangle[n-1][i]);
return res;
}
};
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size();
int total = 0, maxx = -0x3f3f3f3f;
for(const int &num: nums) {
total += num;
maxx = max(maxx,num);
}
if(total % 2 || total/2 < maxx) return false;
int target = total / 2;
vector<int> f(target+1, 0);
f[0] = true;
for(int i = 0; i < n; i++) {
int num = nums[i]; //将nums[i] 换成num速度快了一倍。。
for(int j = target; j >= num; j--)
f[j] |= f[j-num];
}
return f[target];
}
};
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int total = 0, n = nums.size();
for(int num: nums) total += num;
int diff = total - target;
if(diff < 0 || diff % 2) return 0; //若target大于total 或 diff为奇数则直接返回
int neg = diff / 2; //neg = (total - target) / 2
vector<vector<int>> f(n+1, vector<int>(neg+1, 0));
f[0][0] = 1;
for(int i = 1; i <= n; i++) {
int num = nums[i-1];
for(int j = 0; j <= neg; j++) {
if(j < num) {
f[i][j] = f[i-1][j];
} else {
f[i][j] = f[i-1][j] + f[i-1][j-num];
}
}
}
return f[n][neg];
}
};
优化成一维空间
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int total = 0, n = nums.size();
for(int num: nums) total += num;
int diff = total - target;
if(diff < 0 || diff % 2) return 0;
int neg = diff / 2;
vector<int> f(neg+1, 0);
f[0] = 1;
for(int i = 1; i <= n; i++) {
int num = nums[i-1];
for(int j = neg; j >= num; j--) {
f[j] += f[j-num];
}
}
return f[neg];
}
};