给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
如果无解,请返回-1.
数据范围:数组大小满足
, 数组中每个数字都满足
,
要求:时间复杂度
,空间复杂度
。
[5,2,3],20
4
[5,2,3],0
0
[3,5],2
-1
int minMoney(int* arr, int arrLen, int aim ) { int dp[5001], i, j, res; if(arrLen==0) return -1; if(aim==0) return 0; for(i=0; i<aim; i++) dp[i] = aim+1; for(i=0; i<arrLen; i++) dp[arr[i]-1] = 1; for(i=0; i<aim; i++) for(j=0; j<arrLen; j++) if(i>=arr[j]) dp[i] = min(dp[i], dp[i-arr[j]]+1); return (dp[aim-1]<=aim ? dp[aim-1] : -1); }
//dp[i-arr[j]]+1表示:dp[i]扣除遇到的这张单元面值arr[j]之后,剩下的钱数最少能用dp[i-arr[j]]来表示。+1即代表加上当前遇到的单元面值。 /*比如,货币的单元面值[2,3,5]; dp[0]=0; dp[1]=max; dp[2]=1; dp[3]=1; dp[4]=2; dp[5]=2; 求dp[6],首先dp[6-arr[0]]==dp[6-2]==dp[4]==2,表示6元如果扣除2元后剩下的4元面值是可以用最少2张货币来表示的,而除去这两张之外,还要算上2元这一张面值才构成了整个6元。此时一共3张,小于max,因此dp[6]更新为3; 下一轮循环,dp[6-arr[1]]==dp[6-3]==dp[3]==1,表示6元扣除3元后剩下的3元可以从之前的结果中查到最少需要一张货币,1张+1,一共2张,小于当前存储的3张,因此dp[6]更新为2; 下一轮循环,dp[6-arr[2]]==dp[6-5]==dp[1]==max>2,说明无法更新,最小值仍是2,此时循环结束,跳出内层循环,求得dp[6]==2. */