2.一和零|刷题打卡

144 阅读2分钟

一、题目描述:

二、思路分析:

这题就是最简单的01背包题的变种,从只有一种重量限制,改为了有多个重量限制,有趣的是,题目一和零可以说是暗示的很明显了。

这道题是中等题,所以只需要模板稍微改动下就可以了。需要注意的是由于有两种重量,所以使用三层for循环

另外为了稍微提高些效率,我们设置一个二维数组,用于存储每个字符串的0,1个数。

三、AC 代码:

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        int t = strs.size();
        
        int dp[t + 1][m + 1][n + 1];
        int vec[t + 1][2];
        for(int i = 0; i < t; i++){
            string sa = strs[i];
            int a = 0;
            for(int j = 0; j < sa.size(); j++){
                if(sa[j] == '0')a++;
            }
            vec[i + 1][0] = a;
            vec[i + 1][1] = sa.size() - a;
            // printf("%d,%d \n", vec[i + 1][0] , vec[i + 1][1]);
            
        }
        // printf("DP\n");
        for(int i = 0 ; i <= t; i++){
            for(int j = 0 ; j <= m; j++){
                for(int k = 0; k <= n; k++){
                    if(i == 0){
                        dp[i][j][k] = 0;
                        continue;
                    }
                    dp[i][j][k] = dp[i - 1][j][k];
                    if(j >= vec[i][0] && k >= vec[i][1])
                    dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - vec[i][0]][k - vec[i][1]] + 1);
                    
            // printf("%d\n", dp[i][j][k] );
                }
            }
        }
        return dp[t][m][n];
    }
};

四、总结:

这道题三次循环占的空间就有亿点大,我们本着能省就省原则对代码进行优化

我们看原先循环体的代码

	if(i == 0){
            dp[i][j][k] = 0;
            continue;
        }
        dp[i][j][k] = dp[i - 1][j][k]; //代码一
        if(j >= vec[i][0] && k >= vec[i][1])
        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - vec[i][0]][k - vec[i][1]] + 1);
        //代码二

代码一部分只改动了i行,而且是i - 1直接赋值给了i

代码二部分是在使用i-1行的同时,使用了更小的j,k,但如果我们从后往前遍历的话,就可以在保留旧数据的同时,在二维上运行代码。

优化代码如下

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        int t = strs.size();
        
        int dp[m + 1][n + 1];
        int vec[t + 1][2];
        for(int i = 0; i < t; i++){
            string sa = strs[i];
            int a = 0;
            for(int j = 0; j < sa.size(); j++){
                if(sa[j] == '0')a++;
            }
            vec[i + 1][0] = a;
            vec[i + 1][1] = sa.size() - a;
            // printf("%d,%d \n", vec[i + 1][0] , vec[i + 1][1]);
            
        }
        // printf("DP\n");
        for(int i = 0 ; i <= t; i++){
            for(int j = m ; j  >= 0; j--){
                for(int k = n; k >= 0; k--){
                    if(i == 0){
                        dp[j][k] = 0;
                        continue;
                    }
                   
                    if(j >= vec[i][0] && k >= vec[i][1])
                    dp[j][k] = max(dp[j][k], dp[j - vec[i][0]][k - vec[i][1]] + 1);
                    
            // printf("%d\n", dp[i][j][k] );
                }
            }
        }
        return dp[m][n];
    }
};

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情