动态规划学习之力扣练习(一)

概括学习

其实很多人去考虑算法问题都是基于一种暴力求解,尝试枚举,如果枚举成功,可能题也就做出来了,但是枚举失败,就束手无策了,当测试系统告诉你题目运行时间超出限制范围时,还是蛮头秃的。
以前其实还是利用过动态规划去求解问题的,但是我发现这种算法类比于英语单词,你长时间不用,就忘掉了。当我想再次尝试动态规划求解时,我发现除了还记得背包问题四个字以外,脑袋一片空白,所以又去大神的博客里面学习了一下动态规划之背包问题。每次学完这种经典算法都能给自己一种新的感触,所以我决定去力扣专区多刷几道这样的题,好好练习一下。

474. 一和零(力扣)

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

 

示例 1:

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5031 的最大子集是 {
    
    "10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {
    
    "0001","1"}{
    
    "10","1","0"}{
    
    "111001"} 不满足题意,因为它含 41 ,大于 n 的值 3 。
示例 2:

输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:2
解释:最大的子集是 {
    
    "0", "1"} ,所以答案是 2 。
 

提示:

1 <= strs.length <= 600
1 <= strs[i].length <= 100
strs[i] 仅由 '0''1' 组成
1 <= m, n <= 100

怀揣着满腔热血,想来试一试自己所理解的算法套路来尝试求解一下,但是这道题确实给我当头一棒,背包问题所教给我们的是如何去利用背包体积这一个变量去限制选择以求最大价值,这道题却给了两个约束条件,emmmm…仔细思考,其实问题之间还是有共性,背包问题虽然表面上只有体积一个限制因素,但是在动态考虑时,他还是加入了另一个约束条件可以选择的物品个数,虽然这道题有两个限制点,但是由于每个字符串只能使用一次(即有限背包),因此在更新 dp(i, j) 时,i 和 j 都需要从大到小进行枚举。至于为什么要这么理解,相当于背包问题的逆选择。我们用 dp(i, j) 表示使用 i 个 0 和 j 个 1,最多能拼出的字符串数目,那么状态转移方程为:

dp[i][j] = Math.max(1+dp[i-arr[0]][j-arr[1]], dp[i][j]);

其中 k 表示第 k 个字符串,arr[0] 和 arr[1] 表示该字符串中 0 和 1 的个数


    public static int findMaxForm(String[] strs, int m, int n) {
    
    
    	int[][] dp = new int[m+1][n+1];
    	for(int k = 0;k < strs.length;k++) {
    
    
    		int[] arr = intcount(strs[k]);
        	for(int i = m;i >= arr[0];i--) {
    
    
        		for(int j = n;j >= arr[1];j--) {
    
    
        			dp[i][j] = Math.max(1+dp[i-arr[0]][j-arr[1]], dp[i][j]);
        		}
        	}
    	}
    	for(int i = 0;i <= m;i++) {
    
    
    		for(int j = 0;j <= n;j++) {
    
    
    			System.out.print(dp[i][j]+" ");
    		}
    		System.out.println();
    	}
    	return 0;
    }
    public static int[] intcount(String str) {
    
    
    	int[] arr = new int[2];
    	for(int i = 0;i < str.length();i++) {
    
    
    		if(str.charAt(i) == '0')
    			arr[0]++;
    		if(str.charAt(i) == '1')
    			arr[1]++;
    	}
    	return arr;
    }

猜你喜欢

转载自blog.csdn.net/baldicoot_/article/details/115188158
今日推荐