【Leetcode】198. House Robber

198. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
             Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
             Total amount you can rob = 2 + 9 + 1 = 12.

這道題的本質(zhì)相當(dāng)于在一列數(shù)組中取出一個或多個不相鄰數(shù)蔑穴,使其和最大聊浅。

遞歸思路

從第 0 家開始偷,假設(shè)第 0 家偷封救,因?yàn)椴荒芡迪噜彽奶汛埽敲聪麓尉褪菑?[2,n] 開始圣勒,如果第 0 家不偷膝迎,那么下次就是從 [1,n] 開始偷。一直遞歸直到最后一家灰蛙。

解法1:暴力枚舉

class Solution {
    public int rob(int[] nums) {
        return rob(0,nums);
    }
    //1祟剔、思考遞歸退出的邊界條件
    //2、寫遞歸過程
    //3摩梧、返回結(jié)果
    public int rob(int idx,int[] nums) {
        if(idx >= nums.length){
            return 0;
        }
       int a = nums[idx] + rob(idx+2,nums);//假設(shè)第一家偷物延,那下一家就是 idx+2,進(jìn)行遞歸
        int b = 0 + rob(idx+1,nums);//第一家不偷仅父,則為0叛薯,下一家就是 idx+1,再進(jìn)行遞歸
        int c = Math.max(a,b);
        return c;
    }
}

解法2:加緩存

暴力枚舉在 Leetcode 會超時笙纤,而在上面的遞歸樹中耗溜,有很多重復(fù)遞歸遍歷的節(jié)點(diǎn),這里就需要增加緩存粪糙,如果已經(jīng)遍歷過强霎,就直接返回。

class Solution {
    private Map<Integer,Integer> cache = new HashMap<>();
    public int rob(int[] nums) {
        cache.clear();//緩存之前先清理緩存
        return rob(idx,nums);
    }
    //1蓉冈、思考遞歸退出的邊界條件
    //2、緩存判斷在邊界條件后執(zhí)行
    //3轩触、寫遞歸過程
    //4寞酿、在返回結(jié)果的地方進(jìn)行緩存
    //5、返回結(jié)果
    public int rob(int idx,int[] nums) {
        if(idx >= nums.length){
            return 0;
        }
        if(cache.containsKey(idx)) {
            return cache.get(idx);
        }
        int a = nums[idx] + rob(idx+2,nums);
        int b = 0 + rob(idx+1,nums);
        int c = Math.max(a,b);
        cache.put(idx,c);
        return c;
    }
}

解法3:循環(huán)變量

class Solution {
    public int rob(int[] nums) {
        return robot(nums);
    }
    //1脱柱、思考遞歸退出的邊界條件
    //2伐弹、緩存判斷在邊界條件后執(zhí)行
    //3、寫遞歸過程
    //4榨为、在返回結(jié)果的地方進(jìn)行緩存
    //5惨好、返回結(jié)果
    
    //Map緩存
    private Map<Integer,Integer> cache = new HashMap<>();
    public int robot(int[] nums) {
        if(nums==null || nums.length==0){
            return 0;
        }
        if(nums.length == 1) return nums[0];
        //清緩存
        cache.clear();
        int n = nums.length;
        //遞歸自下而上進(jìn)行煌茴,從第 n 家開始偷,直到第一家為止
        //對比上面的遞歸算法日川,寫出循環(huán)就比較簡單
        cache.put(n-1,nums[n-1]);
        cache.put(n-2,Math.max(nums[n-1],nums[n-2]));
        for(int i=n-3; i>=0; --i){
            cache.put(i,Math.max(nums[i] + cache.get(i+2), cache.get(i+1)));
        }
        return cache.get(0);
    }
    
    //數(shù)組緩存
    private int[] caches = new int[10000];
    public int robot1(int[] nums) {
        if(nums==null || nums.length==0){
            return 0;
        }
        if(nums.length == 1) return nums[0];
        int n = nums.length;
        caches[n-1] = nums[n-1];
        caches[n-2] = Math.max(nums[n-1],nums[n-2]);
        for(int i=n-3; i>=0; --i){
            caches[i] = Math.max(nums[i] + caches[i+2], caches[i+1]);
        }
        return caches[0];
    }
}

DP 解題步驟

  1. 設(shè)計(jì)暴力算法蔓腐,找到冗余
  2. 設(shè)計(jì)并存儲狀態(tài)(一維,二維龄句,三維數(shù)組回论,甚至Map)
  3. 遞歸式(狀態(tài)轉(zhuǎn)移方程)
  4. 自底向下計(jì)算最優(yōu)解(編程方式)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市分歇,隨后出現(xiàn)的幾起案子傀蓉,更是在濱河造成了極大的恐慌,老刑警劉巖职抡,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葬燎,死亡現(xiàn)場離奇詭異,居然都是意外死亡缚甩,警方通過查閱死者的電腦和手機(jī)谱净,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹄胰,“玉大人岳遥,你說我怎么就攤上這事≡U” “怎么了浩蓉?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宾袜。 經(jīng)常有香客問我捻艳,道長,這世上最難降的妖魔是什么庆猫? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任认轨,我火速辦了婚禮,結(jié)果婚禮上月培,老公的妹妹穿的比我還像新娘嘁字。我一直安慰自己,他們只是感情好杉畜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布纪蜒。 她就那樣靜靜地躺著,像睡著了一般此叠。 火紅的嫁衣襯著肌膚如雪纯续。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機(jī)與錄音猬错,去河邊找鬼窗看。 笑死,一個胖子當(dāng)著我的面吹牛倦炒,可吹牛的內(nèi)容都是我干的显沈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼析校,長吁一口氣:“原來是場噩夢啊……” “哼构罗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起智玻,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤遂唧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吊奢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盖彭,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年页滚,在試婚紗的時候發(fā)現(xiàn)自己被綠了召边。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡裹驰,死狀恐怖隧熙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幻林,我是刑警寧澤贞盯,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站沪饺,受9級特大地震影響躏敢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜整葡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一件余、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遭居,春花似錦啼器、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鼠次,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腥寇。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工成翩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赦役。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓麻敌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親掂摔。 傳聞我的和親對象是個殘疾皇子术羔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

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