代码随想录算法训练营第43天|1049. 最后一块石头的重量 II,494. 目标和,474.一和零

1049. 最后一块石头的重量 II

力扣题目链接

思路

  • 本题可抽象为将 n 块石头分为两堆,求两堆石头重量的最小差值
  • dp[j] 表示容量为j的背包所能装的最大价值
  • 递推公式:dp[j] = max(dp[j], dp[j - stones[i]] + stone[i]);
  • return sum - 2 * dp[stones.size() - 1];
  • 初始化:dp[0] = 0;
  • 遍历顺序:先物品,后背包,背包倒序遍历

代码

class Solution {
public:
    /*
     * dp[j] 表示容量为j的背包所能装的最大价值
     * 递推公式:dp[j] = max(dp[j], dp[j - stones[i]] + stone[i]);
     * return sum - 2 * dp[stones.size() - 1];
     * 初始化:dp[0] = 0;
     * 遍历顺序:先物品,后背包,背包倒序遍历
    */
    int lastStoneWeightII(vector& stones) {
        int sum = 0;
        for (int i = 0; i < stones.size(); i++) {
            sum += stones[i];
        }
        int target = sum / 2;
        vector dp(target + 1, 0);
        for (int i = 0; i < stones.size(); i++) {
            for (int j = target; j >= stones[i]; j--) {
                dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
            }
        }
        return sum - 2 * dp[target];
    }
};
  • 时间复杂度O(n*target)
  • 空间复杂度O(target)

494. 目标和

力扣题目链接

思路

回溯

  • 设nums数组的和为sum,题目可转化为从数组中取k个数之和为(sum-target)/2的种数
  • 可以通过回溯法求出nums数组的所有子集,当子集和为(sum-target)/2,方法数+1

动态规划

  • 正数堆pos,负数堆sum-pos,则pos-(sum-pos)=target,即pos=(sum+target)/2;
  • 如果(sum+target) % 2 != 0,则说明没有合适的构造方法,返回0
  • dp[i][j] 表示从前i个元素中任取元素使其和为j的方案数
  • 递推公式:dp[i][j] = dp[i-1][j] + dp[i-1]j-nums[i]
  • 初始化:dp[0][0]=1;
  • 遍历:从上到下,从前往后

优化

  • 滚动数组

代码

回溯

class Solution {
public:
    /*
     * 回溯法
     * 设nums数组的和为sum,题目可转化为从数组中取k个数之和为(sum-target)/2的种数
     * 可以通过回溯法求出nums数组的所有子集,当子集和为(sum-target)/2,方法数+1
    */
    int count=0;
    vector path;
    void backtracking(vector& nums, int startIndex, int k) {
        int sum=0;
        for(int i=0;i& nums, int target) {
        int sum=0;
        for(int i=0;i
  • 时间复杂度O(2^n)
  • 空间复杂度O(n)

动态规划

class Solution {
public:
    /*
     * 正数堆pos,负数堆sum-pos,则pos-(sum-pos)=target,即pos=(sum+target)/2;
     * 如果(sum+target) % 2 != 0,则说明没有合适的构造方法,返回0
     * dp[i][j] 表示从前i个元素中任取元素使其和为j的方案数
     * 递推公式:dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]](不取i的方案数+取i的方案数)
     * 初始化:dp[0][0]=1;
     * 遍历:从上到下,从前往后
    */
    int findTargetSumWays(vector& nums, int target) {
        int sum=0;
        for(int i=0;isum) return 0;
        if((sum+target)%2!=0) return 0;
        int pos=(sum+target)/2;
        vector> dp(nums.size()+1,vector(pos+1));
        dp[0][0]=1;
        for(int i=1;i<=nums.size();i++){
            for(int j=0;j<=pos;j++){
                if(j>=nums[i-1])
                    dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i-1]];
                else
                    dp[i][j]=dp[i-1][j]; 
            }
        }
        return dp[nums.size()][pos];
    }
};

优化

class Solution {
public:
    /*
     * 正数堆pos,负数堆sum-pos,则pos-(sum-pos)=target,即pos=(sum+target)/2;
     * 如果(sum+target) % 2 != 0,则说明没有合适的构造方法,返回0
     * dp[i][j] 表示从前i个元素中任取元素使其和为j的方案数
     * 递推公式:dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]](不取i的方案数+取i的方案数)
     * 初始化:dp[0][0]=1;
     * 遍历:从上到下,从前往后
    */
    int findTargetSumWays(vector& nums, int target) {
        int sum=0;
        for(int i=0;isum) return 0;
        if((sum+target)%2!=0) return 0;
        int pos=(sum+target)/2;
        vector dp(pos+1,0);
        dp[0]=1;
        for(int i=0;i=nums[i];j--){
                dp[j]=dp[j]+dp[j-nums[i]];
            }
        }
        return dp[pos];
    }
};
  • 时间复杂度O(n^2)
  • 空间复杂度O(pos)

474.一和零

力扣题目链接

思路

  • 物品重量有两个维度的01背包
  • dp[i][j] 表示装满容量为i和j背包mn的最大子集长度
  • 递推公式:dp[i][j]=max(dp[i][j],dp[i-nums[k][0]][j-nums[k][1]]+1);
  • 初始化 dp[i][j]=0;
  • 先物品再背包,背包倒序

代码

class Solution {
public:
    /*
     * dp[i][j] 表示装满容量为i和j背包mn的最大子集长度
     * 递推公式:dp[i][j]=max(dp[i][j],dp[i-nums[k][0]][j-nums[k][1]]+1);
     * 初始化 dp[i][j]=0;
     * 先物品再背包,背包倒序
    */
    int findMaxForm(vector& strs, int m, int n) {
        int row=strs.size(); //行
        vector> nums(row, vector(2, 0));
        for(int i=0;i> dp(m+1,vector(n+1));
        for(int k=0;k=nums[k][0];i--){
                for(int j=n;j>=nums[k][1];j--){
                    dp[i][j]=max(dp[i][j],dp[i-nums[k][0]][j-nums[k][1]]+1);
                }
            }
        }
        
        return dp[m][n];
    }
};
  • 时间复杂度O(kmn)
  • 空间复杂度O(mn)

你可能感兴趣的:(代码随想录刷题,算法,leetcode,动态规划)