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

视频讲解:

动态规划之背包问题,装满这个背包最多用多少个物品?| LeetCode:474.一和零_哔哩哔哩_bilibili

动态规划之背包问题,装满背包有多少种方法?| LeetCode:494.目标和_哔哩哔哩_bilibili

动态规划之背包问题,这个背包最多能装多少?LeetCode:1049.最后一块石头的重量II_哔哩哔哩_bilibili

 1049. 最后一块石头的重量

思路:本题和划分子集的思想也是一致,但是需要额外主要的就是我们是以石头重量总和一半为目标,全力去凑,希望可以访问半数石头总和这样大小的背包,因而在最后的结果上,我们是将将dp的最后一个元素,需要用石头重量总和减去dp数组的最后元素作为结果。

// 时间复杂度O(n^2)
// 空间复杂度O(n)

class Solution {
    public int lastStoneWeightII(int[] stones) {
        // 本题形成了划分两堆石头的思路,那么本题就和划分子集一样
        int sum = 0;
        for(int i:stones)
            sum+=i;
        int target = sum >> 1;
        int[] dp = new int[target+1];
        for(int i=0; i0; j--){
                if(j >= stones[i])
                    dp[j] = Math.max(dp[j], dp[j-stones[i]]+stones[i]);
            }
        }

        return sum-2*dp[target];
    }
}

494. 目标和

思路:处理两堆子集的思想,将目标和氛围A堆和与B堆和,利用A+B=target, A-B=sum,来总结A为(sum+target)/2,从而确定此时背包的目标容量。另外特殊情况就是target远在sum之外,需要额外讨论。

// 时间复杂度O(n^2)
// 空间复杂度O(n)

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = 0;
        for(int i:nums)
            sum+=i;
        
        if((sum+target)%2 == 1)
            return 0;
        if(sum < Math.abs(target))
            return 0;
        int tar = Math.abs((sum+target)/2);
        int[] dp = new int[tar+1];
        // 和为零的只有一种,
        dp[0] = 1;

        for(int i=0; i=0; j--){
                if(j>=nums[i])
                    dp[j] += dp[j-nums[i]];
                
            }
                
        }

        return dp[tar];
    }
}

474. 一和零

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        //dp[i][j]表示i个0和j个1时的最大子集
        int[][] dp = new int[m + 1][n + 1];
        int oneNum, zeroNum;
        for (String str : strs) {
            oneNum = 0;
            zeroNum = 0;
            for (char ch : str.toCharArray()) {
                if (ch == '0') {
                    zeroNum++;
                } else {
                    oneNum++;
                }
            }
            //倒序遍历
            for (int i = m; i >= zeroNum; i--) {
                for (int j = n; j >= oneNum; j--) {
                    dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }
        return dp[m][n];
    }
}

你可能感兴趣的:(算法)