criskgl
9/23/2019 - 7:55 PM

Coin Change ORIGINAL

public int coinChange(int[] coins, int amount) {
  //Handle edge cases
	if(amount == 0) return 0;
  if(coins.length == 0) return -1;

  int[][] matrix = new int[coins.length][amount];
  /*******************************	
   * 	      1 2 3 4 5 ... amount *
   * COIN 1  FIRST FILLED PART   * 
   * COIN 2 					   *
   * COIN 3					   *
   * ...						   *
   * COIN N					   *
   *******************************/
  /************ NOTE ****************
   * Each cell in matrix is read as:*
   * 								  *
   * MINIMUM NUMBER OF COINS TO GET *
   * AMOUNT J USING I COINS		  *
   **********************************/
  Arrays.sort(coins);
  //fill FIRST FILLED
  int firstCoin = coins[0];
  for(int amountNumber = 1; amountNumber <= amount; amountNumber++){
  	if(amountNumber % firstCoin == 0){
  		matrix[0][amountNumber-1] = amountNumber/firstCoin;
  	}else{
  		matrix[0][amountNumber-1] = 0;
  	}
  }
  for(int indexCoin = 1; indexCoin < coins.length; indexCoin++){//COINS START IN SECOND COIN!!!(because of first filled)
  	for(int amountNumber = 1; amountNumber <= amount; amountNumber++){//in range [1, amount]
  		int coinEntered = coins[indexCoin];
  		if(coinEntered == amountNumber) {//if our coin matches exactly the amount we look for;
  			matrix[indexCoin][amountNumber-1] = 1;
  			continue;
  		}
  		if(coinEntered  > amountNumber){//our coin is useless for the amount considered
  			int minimumNotIncludingEnteredCoin = matrix[indexCoin-1][amountNumber-1];//look how many coins it was needed to get before coinEntered was used
  			matrix[indexCoin][amountNumber-1] = minimumNotIncludingEnteredCoin;
  			continue;
  		}
  		int dif = amountNumber - coinEntered;
  		//we lookup the minimum number of coins using coin up to indexCoin (inclusive) 
  		int minimumCoinsToGetDif = matrix[indexCoin][dif-1];
  		if(minimumCoinsToGetDif == 0){//no ways to get it
  			//take older result from not using coinEntered
  			int minimumNotIncludingEnteredCoin = matrix[indexCoin-1][amountNumber-1];//look how many coins it was needed to get before coinEntered was used
  			matrix[indexCoin][amountNumber-1] = minimumNotIncludingEnteredCoin;
  		}else{//there is a way to get it in minimumCoinsToGetDif times
  			if(matrix[indexCoin-1][amountNumber-1] == 0){
  				matrix[indexCoin][amountNumber-1] = minimumCoinsToGetDif+1;
  				continue;
  			}
  			int minimumNotIncludingEnteredCoin = matrix[indexCoin-1][amountNumber-1];//look how many coins it was needed to get before coinEntered was used
  			int coinsUsedUsingCoinEnteredAndDif = minimumCoinsToGetDif + 1;
  			if(coinsUsedUsingCoinEnteredAndDif < minimumNotIncludingEnteredCoin){
  				 matrix[indexCoin][amountNumber-1] = coinsUsedUsingCoinEnteredAndDif;
  			}else{
  				matrix[indexCoin][amountNumber-1] = minimumNotIncludingEnteredCoin;
  			}
  		}
  	}
  }
  int lastElementInMatrix = matrix[coins.length-1][amount-1];//element in bottom right corner
  if(lastElementInMatrix == 0) return -1;
  return lastElementInMatrix;
}