有一个数组changes,changes中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,对于一个给定值x,请设计一个高效算法,计算组成这个值的方案数。
给定一个int数组changes,代表所有零钱,同时给定它的大小n,另外给定一个正整数x,请返回组成x的方案数,保证n小于等于100且x小于等于10000。
测试样例:
[5,10,25,1],4,15
返回:6
测试样例:
[5,10,25,1],4,0
返回:1
有一个数组changes,changes中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,对于一个给定值x,请设计一个高效算法,计算组成这个值的方案数。
给定一个int数组changes,代表所有零钱,同时给定它的大小n,另外给定一个正整数x,请返回组成x的方案数,保证n小于等于100且x小于等于10000。
[5,10,25,1],4,15
返回:6
[5,10,25,1],4,0
返回:1
import java.util.*; public class Exchange { public int countWays(int[] changes, int n, int x) { // write code here //dp[i][j]表示使用changes[0~i]的钱币组成金额j的方法数 int[][] dp=new int[n][x+1]; //第一列全为1,因为组成0元就只有一种方法 for(int i=0;i<n;i++) dp[i][0]=1; //第一行只有changes[0]的整数倍的金额才能有1种方法 for(int j=0;j*changes[0]<=x;j++){ dp[0][j*changes[0]]=1; } //从位置(1,1)开始遍历 for(int i=1;i<n;i++){ for(int j=1;j<=x;j++){ //关键:使用0~i的钱币组成j-changes[i]金额的方法数+使用0~i-1钱币组成j的方法数 dp[i][j]=dp[i-1][j]+(j-changes[i]>=0?dp[i][j-changes[i]]:0); } } return dp[n-1][x]; } }
import java.util.*; public class Exchange { public int countWays(int[] changes, int n, int x) { // write code here int[] dp = new int[x + 1]; dp[0] = 1; for (int change : changes) { for (int i = 0; i + change <= x; ++i) { dp[i + change] += dp[i]; } } return dp[x]; } }
import java.util.*; public class Exchange { public int countWays(int[] changes, int n, int x) { // 方法一:递归 // return recursion(changes,0,n-1,x); // 方法二:迭代 int[] arr = new int[x + 1]; arr[0] = 1; int i = 0, j = 0; for (i = 0; i < n; ++i) { for (j = 0; j+changes[i] <= x; j++) { arr[j+changes[i]]+=arr[j]; } } return arr[x]; } public int recursion(int[] changes, int begin, int end, int target) { // 边界条件 if (target == 0) return 1; if (begin > end || target < 0) return 0; int count = 0; int times = 0; // 找零的过程中使用了times次changes[begin] // 在后续的找零中,不再使用changes[begin] while (times * changes[begin] <= target) { count += recursion(changes, begin + 1, end, target - times * changes[begin]); ++times; } return count; } }
class Exchange { public: int countWays(vector<int> changes, int n, int x) { int dp[x+1]; for(int i =0;i<=x;i++) dp[i] = 0; dp[0] = 1; for(int i =0;i<n;i++) for(int j = 0;j+changes[i]<=x;j++) dp[j+changes[i]] += dp[j]; return dp[x]; } };
class Exchange { public: int countWays(vector<int> changes, int n, int x) { // write code here int dp[ x+1 ] ; int i,j ; for( i=1; i<=x; i++ ) dp[i] = 0 ; dp[ 0 ] = 1 ;//0元钱找零全部不选,所以方案数为1 for( i=0; i<n; i++ )//dp[j]=dp[j](不选changes[i])+dp[ j-changes[i] ](选择一个changes[i]) for( j=changes[i]; j<=x; j++ ) dp[ j ] = dp[j] + dp[ j-changes[i] ] ; return dp[ x ] ; } };class Exchange {
class Exchange { public: int countWays(vector<int> changes, int n, int x) { // write code here vector<int> brr(x+1,0); brr[0]=1; for(int i=0;i<n;++i) { for(int j=changes[i];j<x+1;++j) { brr[j]+=brr[j-changes[i]]; } } return brr[x]; } };
// 暴力递归 public int countWays1(int[] changes, int n, int x) { if (x == 0) { return 1; } else if (n == 0) { return 0; } int res = countWays1(changes, n - 1, x); if (x >= changes[n - 1]) { for (int k = 1; k <= x / changes[n - 1]; k++) { res += countWays1(changes, n - 1, x - k * changes[n - 1]); } } return res; } // 动态规划 public int countWays2(int[] changes, int n, int x) { int[][] dp = new int[n + 1][x + 1]; for (int i = 0; i <= n; i++) { dp[i][0] = 1; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= x; j++) { dp[i][j] = dp[i - 1][j]; if (j >= changes[i - 1]) { for (int k = 1; k <= j / changes[i - 1]; k++) { dp[i][j] += dp[i - 1][j - k * changes[i - 1]]; } } } } return dp[n][x]; } // 动态规划的空间优化 public int countWays3(int[] changes, int n, int x) { int[] dp = new int[x + 1]; dp[0] = 1; for (int i = 1; i <= n; i++) { for (int j = x; j >= 1; j--) { if (j >= changes[i - 1]) { for (int k = 1; k <= j / changes[i - 1]; k++) { dp[j] += dp[j - k * changes[i - 1]]; } } } } return dp[x]; }
public static int countWays(int[] changes, int n, int x) { // write code here int[] memo = new int[x + 1]; memo[0] = 1; for (int i = 0; i < n; i++) { for (int j = changes[i]; j <= x; j++) { memo[j] += memo[j - changes[i]]; } } return memo[x]; }
class Exchange { public: int countWays(vector<int> changes, int n, int x) { // write code here vector<long> dp(x+1,0); dp[0]=1; for(int i=0;i<n;i++) for(int j=1;j<=x;j++) if(j>=changes[i]) dp[j]+=dp[j-changes[i]]; return dp[x]; } };
class Exchange { public: int countWays(vector<int> changes, int n, int x) { int dp[n][x+1]; memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) dp[i][0] = 1; for(int j=0;j*changes[0]<=x;j++) dp[0][j*changes[0]] = 1; for(int i=1;i<n;i++) for(int j=1;j<=x;j++) { if(j - changes[i] >= 0) dp[i][j] = dp[i-1][j] + dp[i][j-changes[i]]; else dp[i][j] = dp[i-1][j]; } return dp[n-1][x]; } };
//使用动态规划 import java.util.*; public class Exchange { private int[][] map; private int[] changes; private int dp(int x, int y) { //使用前x种货币组成y元的方法数 if (x < 0 || y < 0) return 0; if (map[x][y] != 0) return map[x][y]; //将数据保存在数组中,避免重复递归 if (y == 0) { map[x][y] = 1; return 1; //组成0元的方法数为1 } else { if (x == 0) { map[x][y] = 0; return 0; //0种货币组成非0元的方法数为0 } } if (x == 1) { if (y % changes[0] == 0) { map[x][y] = 1; return 1; //只使用第一种货币,只有当y为此货币整数倍时方法数为1 } } int k = y / changes[x - 1]; //能使用第x种货币的数量上限 int res = 0; for (int i = 0; i <= k; i++) { //是否能使用i个编号为x的货币取决于能否使用x-1种货币组成y - i * changes[x - 1]元 res += dp(x - 1, y - i * changes[x - 1]); } map[x][y] = res; return res; } public int countWays(int[] changes, int n, int x) { this.map = new int[n + 1][x + 1]; this.changes = changes; return dp(n, x); } }
/** * @param changes 零钱面值种类的数组 * @param n changes数组的大小 * @param x 要兑换的钱数 * @return 返回可以兑换的不同方式的数量 */ public int countWays(int[] changes, int n, int x) { // 待兑换的金额是i,可用的范围是0-j-1 // i = x,j = 0-n-1 int[][] dp = new int[x + 1][n]; // 当待兑换的金额是0的时候,都是只有一种 for (int i = 0; i < n; i++) dp[0][i] = 1; // 第1列,待兑换的钱是i,因为只能用第一种零钱,所以只有当是第一种零钱的整数倍的时候,才有一种兑换方法 for (int i = 1; i <= x; i++) { if (i % changes[0] == 0) { dp[i][0] = 1; } } //对于dp[i][j],i是待兑换的钱数,j是changes[0-j]的钱币种类 //dp[i][j] += dp[i][j-1],不用changes[j]这种钱 //dp[i][j] += dp[i-changes[j]][j],用了一张changes[j]这种钱,剩下的待兑换的钱是i-changes[j] //只有以上两种可能 for (int i = 1; i <= x; i++) { for (int j = 1; j < n; j++) { if (i - changes[j] >= 0) dp[i][j] += (dp[i][j-1] + dp[i - changes[j]][j]); else dp[i][j] += dp[i][j-1]; } } return dp[x][n - 1]; }
classExchange {public:intcountWays(vector<int> changes, intn, intx) {// write code hereif(changes.size()==0|| changes.empty() || x<0)return0;vector<int> dp(x+1);for(intj=0;changes[0]*j<=x;j++)dp[changes[0]*j]=1;for(inti=1;i<changes.size();i++)for(intj=1;j<=x;j++)dp[j]+=j-changes[i]>=0? dp[j-changes[i]]:0;returndp[x];}};
# -*- coding:utf-8 -*- class Exchange: def countWays(self,changes,n,x): # write code here dp=[] for i in range(n): dp.append([0]*(x+1)) for i in range(n): dp[i][0]=1 j=0 while j*changes[0]<=x: dp[0][j*changes[0]]=1 j+=1 for i in range(1,n): for j in range(1,x+1): if j-changes[i]>=0: dp[i][j]=dp[i-1][j]+dp[i][j-changes[i]] else: dp[i][j]=dp[i-1][j] return dp[-1][-1]
class Exchange { public: int countWays(vector<int> changes, int n, int x) { if (changes.empty() || n <= 0 || x < 0) { return 0; } int rows = changes.size(); int cols = x; vector<vector<int>> dp(rows + 1, vector<int>(cols + 1, 0)); for (int i = 0; i <= rows; i++) { dp[i][0] = 1; } for (int i = 1; i <= rows; i++) { for (int j = 1; j <= cols; j++) { if (j - changes[i - 1] >= 0) { dp[i][j] += dp[i][j - changes[i - 1]]; } dp[i][j] += dp[i - 1][j]; } } return dp[rows][cols]; } };
public int countWays(int[] changes, int n, int x) {
//初始化
int[] dp = new int[x + 1];
for (int i = 0; i < x + 1; i++)
dp[i] = i % changes[changes.length - 1] == 0 ? 1 : 0;
//动态更新
for (int i = changes.length - 2; i >= 0; i--) {
for (int j = 0; j < x + 1; j++) {
dp[j] += j >= changes[i] ? dp[j - changes[i]] : 0;
}
}
return dp[x];
}