DP #322 Coin Change

Link: https://leetcode.com/problems/coin-change

class Solution {
    public int coinChange(int[] coins, int amount) {
        int n = coins.length;
        // int[][] dp = new int[n][amount+1];
        // for(int[] i: dp) Arrays.fill(i,-1);

        // int ans = func(coins.length-1,amount,coins,dp);
        int ans = tabOpt(coins,amount,n);
        if(ans >=(int)Math.pow(10,9)) return -1;
        return ans;
    }

    // Space optimised Tabulation solution
    int tabOpt(int[] c, int am, int n){
        int[] dp = new int[am+1];
        for(int i=1;i<=am;i++) dp[i] = (i%c[0]==0)?i/c[0]: (int)Math.pow(10,9);

        for(int i=1;i<n;i++){
            int[] cur = new int[am +1];
            for(int j=1;j<=am;j++){
                int tk = (j-c[i]>=0)? (1+cur[j-c[i]]):(int)Math.pow(10,9);
                int ntk = dp[j];
                cur[j] = Math.min(tk,ntk);
            }
            dp=cur;
        } 
        return dp[am];
    }

    // Tabulation solution
    int tab(int[] c, int am, int n){
        int[][] dp = new int[n][am+1];
        for(int i=1;i<=am;i++) dp[0][i] = (i%c[0]==0)?i/c[0]: (int)Math.pow(10,9);

        for(int i=1;i<n;i++){
            for(int j=1;j<=am;j++){
                int tk = (j-c[i]>=0)? (1+dp[i][j-c[i]]):(int)Math.pow(10,9);
                int ntk = dp[i-1][j];
                dp[i][j] = Math.min(tk,ntk);
            }
        } 
        return dp[n-1][am];
    }

    // Recursive solution
    int func(int i, int am, int[] c, int[][] dp){
        if(am<0) return (int)Math.pow(10,9);
        if(am==0) return 0;
        if(i==0) return dp[i][am] = (am%c[i]==0)?am/c[i]:(int)Math.pow(10,9);
        if(dp[i][am]!=-1) return dp[i][am];

        int tk = 1 + func(i, am-c[i], c,dp);
        int ntk = func(i-1,am,c,dp);
        return dp[i][am] = Math.min(tk,ntk);
    }
}