动态规划基础问题,力扣322
public static int coinChange(int[] coins, int amount)
{
if(amount==0)
return 0;
if(coins.length==1)
{
if(amount%coins[0]!=0)
return -1;
else
return amount/coins[0];
}
int[] dp = new int[amount+1];
for (int i = 0; i <= amount; i++)
{
dp[i] = -1;
}
dp[0] = 0;
Arrays.sort(coins);
int res = 0;
int size = coins.length-1;
for (int i = 1; i <= amount; i++) //i:当前要求的面额的数量
{
for (int i1 = 0; i1 < coins.length; i1++) //循环遍历所有可用的硬币的面值
{
if(coins[i1]<=i&&dp[i-coins[i1]]!=-1) //如果当前所求面额大于当前遍历到的硬币面值
{
if(dp[i]==-1||dp[i]>1+dp[i-coins[i1]]) //如果当前面值的最优解还未出现或者当前面值减去遍历到的面额后所需要的数量少于
{
dp[i] = 1+dp[i-coins[i1]];
}
}
}
}
//System.out.println(Arrays.toString(dp));
return dp[amount];
}
主要代码如下
for (int i = 1; i <= amount; i++) //i:当前要求的面额的数量
{
for (int i1 = 0; i1 < coins.length; i1++) //循环遍历所有可用的硬币的面值
{
if(coins[i1]<=i&&dp[i-coins[i1]]!=-1) //如果当前所求面额大于当前遍历到的硬币面值
{
if(dp[i]==-1||dp[i]>1+dp[i-coins[i1]]) //如果当前面值的最优解还未出现或者当前面值减去遍历到的面额后所需要的数量少于
{
dp[i] = 1+dp[i-coins[i1]];
}
}
}
}
最外层for循环是为了循环计算从金额1到金额amount的最优解,i = 0时已被赋初值0,因为0张的最优解就是0
内层for循环是为了在每一次计算金额时,把所有的可用面值硬币遍历一遍,为了查看当前遍历的金额下(求解最优解的金额),能够使用的面值有什么。
第一个if中用来判断当前第二层for循环中所遍历到的硬币面值是否可用(即所用的硬币金额的最大值不应该超过所求的金额面值),同时判断当前最外层for循环所遍历到的金额如果减去当前第二层for循环遍历到的硬币的数额是不是有最优解。如果有最优解才可进行下一步的判断。
即假如当前需要求10元的最优解,即外圈for遍历到10,且此时内圈硬币的面值遍历到2元,即内圈for遍历到2时,首先判断2元硬币的面额是不是大于10,很显然不大于,再判断10-2,即8元有没有算出最优解,如果有,进入下一步判断。
最后一个if用于判断当前最外圈for遍历到的面值是不是没有解(即10是不是还没有解),或者算出的最优解的数值比外圈for遍历到的数值减去第二个for的数值后加上这一个硬币的个数多(即是不是那个2元一个硬币的和8元的最优解加起来的个数比之前算出来的解小),如果满足一项,那么就更新该数值的解。
最后算出来的值,即所想要求的那个数值的最优解被放在和他数值等位的数组位置中,即dp[amount]中。