【LeetCode416】【DP】每日一题day33

32 篇文章 0 订阅
4 篇文章 0 订阅

好久不见~

我一开始看到,元素和是一个定值嘛,我觉得可以转换成LeetCode40 组合总和II,找nums里面和为一个定值的元素,就写了回溯,结果超时了

class Solution {
public:
    bool recall(int cnt, int sum, map<int, int> appearNumber, vector<int> nums)
    {
        if (sum == 0) return true;
        if (sum < 0) return false;
        if (cnt >= nums.size()) return false;
        for (int i = 1; i <= appearNumber[nums[cnt]]; i++)
        {
            if (recall(cnt + appearNumber[nums[cnt]], sum - i * nums[cnt], appearNumber, nums) == true)
            {
                return true;
            }
        }
        if (recall(cnt + appearNumber[nums[cnt]], sum, appearNumber, nums) == true)
        {
            return true;
        }
        return false;
    }

    bool canPartition(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        map<int, int> appearNumber;
        int size = nums.size();
        appearNumber[nums[0]] = 1;
        int sum = nums[0];
        for (int i = 1; i < size; i++)
        {
            sum += nums[i];
            if (nums[i] == nums[i - 1])
            {
                appearNumber[nums[i]]++;
            }
            else
            {
                appearNumber[nums[i]] = 1;
            }
        }
	
		// 注意map的遍历
        // map<int, int>::iterator it;
        // for (it = appearNumber.begin(); it != appearNumber.end(); it++)
        // {
        //     printf("%d %d\n", it->first, it->second);
        // }
        
        if (sum % 2 != 0) return false;
        sum /= 2;  
        if (nums[size - 1] > sum) return false;
        else if (nums[size - 1] == sum) return true;

        return recall(0, sum, appearNumber, nums);
    }
};

标准解法是dp嘛,在序列中选取若干个数,让它们的和刚好等于一个给定值。【如果经验丰富的话这里应该能看出来是01背包问题】

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int size = nums.size();
        if (size == 1) return false;

        int sum = nums[0];
        int maxNum = nums[0];
        for (int i = 1; i < size; i++)
        {
            sum += nums[i];
            if (nums[i] > maxNum)
            {
                maxNum = nums[i];
            }
        }
        if (sum % 2 != 0) return false;
        sum /= 2;  
        if (maxNum > sum) return false;
        else if (nums[size - 1] == sum) return true;

        bool f[size][sum + 1];
        memset(f, false, sizeof(f));
        //f[0][nums[0]] = true;

        for (int i = 0; i < size; i++)
        {
            f[i][nums[i]] = true;
            f[i][0] = true;
        }

        for (int i = 1; i < size; i++)
        {
            for (int j = 1; j <= sum; j++)
            {
                if (j >= nums[i])
                {
                    f[i][j] = f[i - 1][j - nums[i]] | f[i - 1][j];
                }
                else
                {
                    f[i][j] = f[i - 1][j];
                }
            }
        }
        return f[size - 1][sum];
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值