LeetCode刷题笔记12
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]