Leetcode - Coin Change

My code:

public class Solution {
    private int min = -1;
    public int coinChange(int[] coins, int amount) {
        if (coins == null || coins.length == 0 || amount < 0)
            return -1;
        else if (amount == 0)
            return 0;
        Arrays.sort(coins);
        int ret = helper(coins, amount, coins.length - 1, 0);
        return (ret == Integer.MAX_VALUE ? -1 : ret);
    }
    
    private int helper(int[] coins, int amount, int end, int counter) {
        if (amount == 0)
            return counter;
        else if (amount < 0)
            return Integer.MAX_VALUE;
        else if (end < 0)
            return Integer.MAX_VALUE;
        int contain = helper(coins, amount - coins[end], end, counter + 1); // contain coins[end]
        int miss = helper(coins, amount, end - 1, counter); // miss coins[end]
        return Math.min(contain, miss);
    }
}

這個解法是超時的趟薄。
采用了 backtracing 的思想堪夭,復(fù)雜度達(dá)到了驚人的 O(2 ^ n)
其實這道題目原型不就是 combination 嗎?
combination 要求你返回所有組合,而這個,是讓你返回所有組合中size最小的庐椒。
看了答案后,正確解法如下蚂踊,

My code:

public class Solution {
    public int coinChange(int[] coins, int amount) {
        if (coins == null || coins.length == 0 || amount < 0)
            return 0;
        if (amount == 0)
            return 0;
        int[][] dp = new int[amount + 1][coins.length]; // for getting amount i, using coins[] from 0 to j, how many coins
        for (int i = 0; i < dp[0].length; i++)
            dp[0][i] = 0;
        for (int i = 1; i < dp.length; i++) {
            for (int j = 0; j < dp[0].length; j++) {
                int contain = -1;
                if (i - coins[j] >= 0)
                    contain = (dp[i - coins[j]][j] == -1 ? -1 : dp[i - coins[j]][j] + 1);
                int miss = -1;
                if (j >= 1)
                    miss = dp[i][j - 1];
                if (contain == -1 && miss == -1)
                    dp[i][j] = -1;
                else if (contain == -1 || miss == -1)
                    dp[i][j] = (contain == -1 ? miss : contain);
                else
                    dp[i][j] = Math.min(contain, miss);
            }
        }
        return dp[dp.length - 1][dp[0].length - 1];
    }
}

采用backtracking 的方法约谈,為什么復(fù)雜度會那么高?
因為里面有大量的重復(fù)的case犁钟,一次次地被再次訪問棱诱。

而使用了 dp, 將已經(jīng)完成的結(jié)果全部存起來涝动,下次要用的時候迈勋,直接訪問,就可以了醋粟。不用再次推導(dǎo)靡菇。這也是dp的意義。
**
將已經(jīng)獲得的結(jié)果存起來米愿,下次使用就不需要再花時間求了厦凤。避免了重復(fù)時間。
**

參考網(wǎng)頁:
http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/

另外吗货,這道題目要求的是最小coins組合泳唠,返回個數(shù)。
也可以求宙搬,達(dá)到target的所有組合個數(shù)笨腥。這樣, dp[i][j] 的含義,就是達(dá)到i勇垛,由coins[0] - [j]脖母,有多少種組合個數(shù)。 dp[0][j] = 1

也可以闲孤,再進(jìn)一步谆级,做成 combination.
Combination 復(fù)雜度是 O(2 ^ n)
而用這個dp,思路如下,
使用一個HashMap, key = i * row + j , which should be unique
value = its set for target.
那么肥照,dp[i][j]時脚仔,
首先,
如果 dp[ i - coins[j] ] [j] = 0, 那么 (i, j) -> empty set
如果 dp[ i - coins[j] ] [j] > 0, 那么dp[i][j] = dp[ i - coins[j] ] [j] + 1,
然后舆绎,取出( ( i - coins[j] ) , j) 對應(yīng)的set鲤脏,深拷貝一份,插入 coins[ i ],
將整體插入到 (i, j) -> set 的HashMap 中吕朵。
我覺得是可行的猎醇。但可能會出現(xiàn)重復(fù)問題。

dp是個很大的問題努溃,最近的理解在逐步加深硫嘶。
去除掉重復(fù)情況,類似于一個HashMap

另外梧税,HashSet沦疾, contains的復(fù)雜度,最壞情況可能是O(n)
HashSet 的底層是由 HashMap 實現(xiàn)的贡蓖。

Anyway, Good luck, Richardo!

My code:

public class Solution {
    public int coinChange(int[] coins, int amount) {
        if (coins == null || coins.length == 0) {
            return -1;
        }
        if (amount == 0) {
            return 0;
        }
        
        Arrays.sort(coins);
        int[] dp = new int[amount + 1];
        for (int i = 0; i < coins.length; i++) {
            if (coins[i] <= amount) {
                dp[coins[i]] = 1;
            }
        }
        
        for (int i = 1; i <= amount; i++) {
            if (dp[i] != 0) {
                continue;
            }
            else {
                int j = coins.length - 1;
                int base = Integer.MAX_VALUE;
                for (; j >= 0; j--) {
                    if (coins[j] > i) {
                        continue;
                    }
                    else if (dp[i - coins[j]] == 0) {
                        continue;
                    }
                    else {
                        base = Math.min(base, 1 + dp[i - coins[j]]);
                    }
                }
                dp[i] = (base == Integer.MAX_VALUE ? 0 : base);
            }
        }
        
        return dp[amount] == 0 ? -1 : dp[amount];
    }
}

不知道為什么之前會用 二維DP來做曹鸠?
這次做煌茬,直接就想到了一唯DP斥铺,并且寫了出來,雖然提交了好幾次坛善。
這道題目和 perfect squares 很相似晾蜘,都是用幾個給定的數(shù),來湊這個數(shù)眠屎,求最小的次數(shù)剔交。
我的思路是,對于不能湊出來的改衩,就讓他的值保持0岖常,
比如,
我們要湊一個 i
我們有 coins[],
那么 就
拿coins里面的一個個面值來試葫督,
如果 dp[i - coins[i]] == 0, 那么就代表不能被湊出來竭鞍,那么就換下一個面值。
如果可以被湊出來橄镜,求出最小的那個值偎快。
dp[i] 表示的是, 湊錢到i需要的最少的個數(shù)洽胶。
O(amount * coins.length)
Anyway, Good luck, Richardo! -- 08/18/2016

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晒夹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丐怯,老刑警劉巖喷好,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異读跷,居然都是意外死亡绒窑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門舔亭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來些膨,“玉大人,你說我怎么就攤上這事钦铺《┪恚” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵矛洞,是天一觀的道長洼哎。 經(jīng)常有香客問我,道長沼本,這世上最難降的妖魔是什么噩峦? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮抽兆,結(jié)果婚禮上识补,老公的妹妹穿的比我還像新娘。我一直安慰自己辫红,他們只是感情好凭涂,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贴妻,像睡著了一般切油。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上名惩,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天澎胡,我揣著相機(jī)與錄音,去河邊找鬼娩鹉。 笑死攻谁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的底循。 我是一名探鬼主播巢株,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熙涤!你這毒婦竟也來了阁苞?” 一聲冷哼從身側(cè)響起困檩,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎那槽,沒想到半個月后悼沿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡骚灸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年糟趾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甚牲。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡义郑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丈钙,到底是詐尸還是另有隱情非驮,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布雏赦,位于F島的核電站劫笙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏星岗。R本人自食惡果不足惜填大,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俏橘。 院中可真熱鬧允华,春花似錦、人聲如沸敷矫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曹仗。三九已至,卻和暖如春蠕搜,著一層夾襖步出監(jiān)牢的瞬間怎茫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工妓灌, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留轨蛤,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓虫埂,卻偏偏與公主長得像祥山,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子掉伏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗缝呕。 張土汪:刷leetcod...
    土汪閱讀 12,737評論 0 33
  • 動態(tài)規(guī)劃(Dynamic Programming) 本文包括: 動態(tài)規(guī)劃定義 狀態(tài)轉(zhuǎn)移方程 動態(tài)規(guī)劃算法步驟 最長...
    廖少少閱讀 3,268評論 0 18
  • 個人學(xué)習(xí)批處理的初衷來源于實際工作澳窑;在某個迭代版本有個BS(安卓手游模擬器)大需求,從而在測試過程中就重復(fù)涉及到...
    Luckykailiu閱讀 4,702評論 0 11
  • 326. Power of Three Given an integer, write a function to...
    跑者小越閱讀 2,131評論 0 1
  • 像白云一樣的飄過來供常, 像流水一樣的流過來摊聋, 像蒲公英一樣的飛過來。 不需要濃妝艷抹栈暇, 只是淡雅高貴B椴谩! 像一陣清風(fēng)...
    千劫已過閱讀 279評論 0 0