343
class Solution {
private:
vector<int> memo;
int breakInteger(int n){
if(n == 1)
return 1;
if(memo[n] != -1)
return memo[n];
int res = -1;
for(int i = 1 ; i < n ; i ++)
{
int tmp = max(i * (n - i) , i * breakInteger(n - i)); //別忘記 i*(n-i)
res = max(res, tmp);
}
memo[n] = res;
return res;
}
public:
int integerBreak(int n) {
memo = vector<int>(n+1, -1);
return breakInteger(n);
}
};
動態規劃
class Solution {
private:
vector<int> memo;
public:
int integerBreak(int n) {
memo = vector<int>(n+1, -1);
memo[1] = 1;
for(int i=2; i<=n; i++)
{
for(int j=1; j<=i-1; j++)
{
int tmp = max(j*(i-j), j*memo[i-j]);
memo[i] = max(memo[i], tmp);
}
}
return memo[n];
}
};
62
class Solution {
public:
int uniquePaths(int m, int n) {
memo = vector<vector<int>>(m, vector<int>(n, 1)); //memo[i][j] 保存到 節點[i][j] 的路徑個數
//memo[i][j] = memo[i-1][j] + memo[i][j-1]
for(int i=1; i<m; i++)
for(int j=1; j<n; j++)
memo[i][j] = memo[i-1][j] + memo[i][j-1];
return memo[m-1][n-1];
}
private:
vector<vector<int>> memo;
};
198
class Solution {
public:
int rob(vector<int>& nums) {
memo = vector<int>(nums.size(), -1);
return help(nums, 0);
}
private:
vector<int> memo;
int help(vector<int>& nums, int index)
{
if(index >= nums.size())
return 0;
if(memo[index] != -1)
return memo[index];
int ret = 0;
for(int i=index; i<nums.size(); i++)
{
ret = max(nums[i]+help(nums, i+2), ret);
}
memo[index] = ret;
return ret;
}
};
動態規劃
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if( n == 0 )
return 0;
// the max profit for robbing nums[0...i]
vector<int> memo(n, 0);
memo[0] = nums[0];
for(int i = 1 ; i < n ; i ++)
memo[i] = max(memo[i - 1],
nums[i] + (i - 2 >= 0 ? memo[i - 2] : 0));
return memo[n-1];
}
private:
vector<int> memo;
};
213
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if( n == 0 )
return 0;
if(n == 1)
return nums[0];
// the max profit for robbing nums[0...i-1]
vector<int> memo(n, 0);
memo[0] = nums[0];
for(int i = 1 ; i < n-1 ; i ++)
memo[i] = max(memo[i - 1],
nums[i] + (i - 2 >= 0 ? memo[i - 2] : 0));
// the max profit for robbing nums[1...i]
vector<int> memo1(n, 0);
memo1[0] = 0;
for(int i = 1 ; i < n; i ++)
memo1[i] = max(memo1[i - 1],
nums[i] + (i - 2 >= 0 ? memo1[i - 2] : 0));
return max(memo[n-2], memo1[n-1]);
}
private:
vector<int> memo;
vector<int> memo1;
};
337
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int rob(TreeNode* root) {
if(!root)
return 0;
int ret = help(root);
return ret;
}
private:
unordered_map<TreeNode*, int> memo;
int help(TreeNode *node)
{
if(!node)
return 0;
if(memo.find(node) != memo.end())
return memo[node];
int tmp = 0;
if(node->left)
tmp += help(node->left->left) + help(node->left->right);
if(node->right)
tmp += help(node->right->left) + help(node->right->right);
tmp = max(node->val+tmp, help(node->left)+help(node->right)); //比較:當前節點+左、右節點的子樹 左子樹+右子樹
memo[node] = tmp;
return tmp;
}
};
300
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.size() == 0)
return 0;
memo = vector<int>(nums.size(), 1); //memo[i]:以 nums[i] 爲結尾的最長上升子序列的長度
for(int i=1; i<nums.size(); i++)
for(int j=0; j<i; j++)
{
if(nums[j] < nums[i])
memo[i] = max(memo[i], memo[j]+1);
}
sort(memo.begin(), memo.end());
return memo[nums.size()-1];
}
private:
vector<int> memo;
};
動態規劃
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
bool compare(const Interval& a, const Interval& b)
{
if(a.start != b.start)
return a.start < b.start;
return a.end < b.end;
}
class Solution {
public:
int eraseOverlapIntervals(vector<Interval>& intervals)
{
if(intervals.size() == 0)
return 0;
sort(intervals.begin(), intervals.end(), compare);
//memo[i] : intervals[0...i]所包含的最大不重疊區間個數
memo = vector(intervals.size(), 1);
for(int i=1; i<intervals.size(); i++)
for(int j=0; j<i; j++)
{
if(intervals[j].end <= intervals[i].start)
memo[i] = max(memo[i], memo[j]+1);
}
sort(memo.begin(), memo.end());
return intervals.size() - memo[intervals.size()-1];
}
private:
vector<int> memo;
};
貪心
bool compare(const Interval &a, const Interval &b){
if(a.end != b.end)
return a.end < b.end;
return a.start < b.start;
}
/// 時間複雜度: O(n)
/// 空間複雜度: O(n)
class Solution {
public:
int eraseOverlapIntervals(vector<Interval>& intervals) {
if(intervals.size() == 0)
return 0;
sort(intervals.begin(), intervals.end(), compare);
int res = 1;
int pre = 0;
for(int i = 1 ; i < intervals.size() ; i ++)
if(intervals[i].start >= intervals[pre].end){
res ++;
pre = i;
}
return intervals.size() - res;
}
};
F(i, c):在i個物體中選擇,揹包容量爲c,價值最大
F(i, c)= max(F(i-1,c), v[i]+F(i-1,c-w[i]))
class Knapsack01{
private:
vector<vector<int>> memo;
// 選擇 [0...index]的物品,填充容積爲c的揹包的最大價值
int bestValue(const vector<int> &w, const vector<int> &v, int index, int c){
if(c <= 0 || index < 0)
return 0;
if(memo[index][c] != -1)
return memo[index][c];
int res = bestValue(w, v, index-1, c);
if(c >= w[index])
res = max(res, v[index] + bestValue(w, v, index - 1, c - w[index]));
memo[index][c] = res;
return res;
}
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
int n = w.size();
if(n == 0 || C == 0)
return 0;
memo = vector<vector<int>>(n, vector<int>(C+1, -1));
return bestValue(w, v, n - 1, C);
}
};
動態規劃
//時間複雜度: O(n * C) 其中n爲物品個數; C爲揹包容積
//空間複雜度: O(n * C)
class Knapsack01{
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
int n = w.size();
if(n == 0 || C == 0)
return 0;
vector<vector<int>> memo(n, vector<int>(C + 1,0));
for(int j = 0 ; j <= C ; j ++)
memo[0][j] = (j >= w[0] ? v[0] : 0 );
for(int i = 1 ; i < n ; i ++)
for(int j = 0 ; j <= C ; j ++){
memo[i][j] = memo[i-1][j];
if(j >= w[i])
memo[i][j] = max(memo[i][j], v[i] + memo[i - 1][j - w[i]]);
}
return memo[n - 1][C];
}
};
優化1:
/// 時間複雜度: O(n * C) 其中n爲物品個數; C爲揹包容積
/// 空間複雜度: O(C), 實際使用了2*C的額外空間
class Knapsack01{
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
int n = w.size();
if( n == 0 && C == 0 )
return 0;
vector<vector<int>> memo(2, vector<int>(C + 1, 0));
for(int j = 0 ; j <= C ; j ++)
memo[0][j] = (j >= w[0] ? v[0] : 0);
for(int i = 1 ; i < n ; i ++)
for(int j = 0 ; j <= C ; j ++){
memo[i % 2][j] = memo[(i-1) % 2][j];
if(j >= w[i])
memo[i % 2][j] = max(memo[i % 2][j], v[i] + memo[(i-1) % 2][j - w[i]]);
}
return memo[(n-1) % 2][C];
}
};
優化2:只使用一行大小爲C的數組
/// 時間複雜度: O(n * C) 其中n爲物品個數; C爲揹包容積
/// 空間複雜度: O(C), 只使用了C的額外空間
class Knapsack01{
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
intn = w.size();
if(n == 0 || C == 0)
return 0;
vector<int> memo(C+1,0);
for(int j = 0 ; j <= C ; j ++)
memo[j] = (j >= w[0] ? v[0] : 0);
for(int i = 1 ; i < n ; i ++)
for(int j = C ; j >= w[i] ; j --)
memo[j] = max(memo[j], v[i] + memo[j - w[i]]);
return memo[C];
}
};
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
for(int i=0; i<nums.size(); i++)
sum += nums[i];
if(sum%2 != 0)
return false;
memo = vector<vector<int>>(nums.size(), vector<int>(sum/2+1, -1));
return help(nums, nums.size()-1, sum/2);
}
private:
vector<vector<int>> memo; //memo[i][c] -1:沒記錄過
// 0:nums[0...i]無法填滿 大小爲 C 的揹包
// 1:nums[0...i] 可以填滿 大小爲 C 的揹包
bool help(vector<int> &nums, int index, int C) // nums[0...index] 能否填滿 大小爲 C 的揹包
{
if(C == 0)
return true;
if(index < 0 || C < 0)
return false;
if(memo[index][C] != -1)
return (memo[index][C] == 0)?false:true;
memo[index][C] = help(nums, index-1, C) || help(nums, index-1, C-nums[index]);
return memo[index][C];
}
};