LeetCode典型題——動態規劃

在這裏插入圖片描述
在這裏插入圖片描述

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];
    }
};

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章