LeetCode刷题12--分割等和子集、零钱兑换 II

本文介绍了如何使用背包问题的动态规划方法解决LeetCode中的416分割等和子集问题,同时分享了518零钱兑换II的两种代码实现及其优化策略。通过实例演示和代码展示,帮助理解这两个经典的动态规划问题。
摘要由CSDN通过智能技术生成

416. 分割等和子集

链接

题目描述

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意:

每个数组中的元素不会超过 100
数组的大小不会超过 200

示例 1:

输入: [1, 5, 11, 5]

输出: true

解释: 数组可以分割成 [1, 5, 5] 和 [11].

示例 2:

输入: [1, 2, 3, 5]

输出: false

解释: 数组不能分割成两个元素和相等的子集.

思路

背包问题
dp[i][j]表示前i个nums[:i]是否有满足和为j的组合。
if j-nums[i-1]:不加入物体,则dp[i][j]的值和dp[i-1][j]
有关。else:dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i-1]](第i个物体放或者不放)

代码

python

class Solution(object):
    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        total=sum(nums)
        if total%2==1:
            return False
        N=total//2
        n=len(nums)
        dp=[]
        for i in range(n+1):
            tmp=[]
            for j in range(N+1):
                tmp.append(False)
            dp.append(tmp)
        for i in range(n+1):
            dp[i][0]=True
        for i in range(1,n+1):
            for j in range(1,N+1):
                if j-nums[i-1]<0:
                    dp[i][j]=dp[i-1][j]
                else:
                    dp[i][j]=dp[i-1][j] or dp[i-1][j-nums[i-1]]
        return dp[n][N]

c++

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        int l=nums.size();

        for(int i=0;i<l;i++) sum+=nums[i];
        if (sum%2==1) return false;
        int N=sum/2;
        
        vector<vector<bool>> dp(l+1,vector<bool>(N+1,false));
        for (int i=0;i<=l;i++){
            dp[i][0]=true;
        }
        for (int i=1;i<=l;i++){
            for(int j=1;j<=N;j++){
                if (j-nums[i-1]<0) dp[i][j]=dp[i-1][j];
                else{
                    dp[i][j]=(dp[i-1][j] || dp[i-1][j-nums[i-1]]);
                }
            }
        }
        return dp[l][N];

    }
};

518. 零钱兑换 II

链接

题目描述

给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。

示例 3:

输入: amount = 10, coins = [10]
输出: 1

代码

class Solution(object):
    def change(self, amount, coins):
        """
        :type amount: int
        :type coins: List[int]
        :rtype: int
        """
        n=len(coins)
        dp=[]
        for i in range(n+1):
            tmp=[]
            for j in range(amount+1):
                tmp.append(0)
            dp.append(tmp)
        for i in range(n+1):
            dp[i][0]=1
        for i in range(1,n+1):
            for j in range(1,amount+1):
                if (j-coins[i-1]<0):
                    dp[i][j]=dp[i-1][j]
                else:
                    dp[i][j]+=dp[i-1][j]+dp[i][j-coins[i-1]]
        return dp[-1][-1]

优化

class Solution(object):
    def change(self, amount, coins):
        """
        :type amount: int
        :type coins: List[int]
        :rtype: int
        """
        n=len(coins)
        dp=[0 for i in range(amount+1)]
        dp[0]=1
        for i in range(n):
            for j in range(coins[i],amount+1):
                dp[j]+=dp[j-coins[i]]
        return dp[-1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值