日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[dp]leetcode 198. House Robber

發(fā)布時(shí)間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [dp]leetcode 198. House Robber 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

輸入:一個(gè)數(shù)組nums,每一個(gè)元素nums[i]表示第i個(gè)房間的價(jià)值。
輸出:一個(gè)搶劫犯能搶到又不會(huì)被警察發(fā)現(xiàn)的最大價(jià)值。
規(guī)則:如果搶劫犯搶了相鄰房間,那么報(bào)警裝置就會(huì)觸發(fā),警察會(huì)得到通知。
分析:我可以從第0個(gè)房間開(kāi)始,可能搶,也可能不搶,一直到最后一個(gè)房間,得到的價(jià)值取最大值就是結(jié)果。用回溯法吧。

public class HouseRobber198 {private int[] nums;private int max = 0;public int rob(int[] nums) {this.nums = nums;max = 0;rob(0,0,true);return max;}private void rob(int idx,int value,boolean robable){if(idx==nums.length){max = Math.max(max,value);}else{//System.out.println(idx+" "+robbed+" "+value);int idx2 = robable?1:0;if(robable){rob(idx+1,value+nums[idx],false);}rob(idx+1,value,true);}} }

分析2:這樣寫(xiě)完,畫(huà)決策分析樹(shù),或者打印idx,robbed,value,就會(huì)發(fā)現(xiàn)有些是重復(fù)的。2 false 重復(fù)了兩次。因?yàn)橐?jì)算的是最大價(jià)值,所以只需要保留一個(gè)最大值。所以我們可以使用緩存減少計(jì)算量。

0 false 0 1 true 1 2 false 1 3 true 4 3 false 1 1 false 0 2 true 2 3 false 2 2 false 0 3 true 3 3 false 0 private int[] nums;private int max = 0;private int[][] memo;public int rob(int[] nums) {this.nums = nums;max = 0;memo = new int[nums.length][2];rob(0,0,true);return max;}private void rob(int idx,int value,boolean robable){if(idx==nums.length){max = Math.max(max,value);}else{//System.out.println(idx+" "+robbed+" "+value);int idx2 = robable?1:0;if(value<memo[idx][idx2]){return;}memo[idx][idx2]=value;if(robable){rob(idx+1,value+nums[idx],false);}rob(idx+1,value,true);}}

分析3:把以上代碼改為迭代版本。把變量名memo改為dp。

public int rob(int[] nums) {if(nums==null || nums.length==0) return 0;int n = nums.length;int[][] dp = new int[n][2];dp[0][0] = 0;dp[0][1] = nums[0];for(int i=1;i<n;i++){dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]);dp[i][1] = dp[i-1][0]+nums[i];}return Math.max(dp[n-1][0],dp[n-1][1]);}

看著寫(xiě)出來(lái)的dp代碼我發(fā)現(xiàn)可以這樣整理自己的邏輯。

給定一個(gè)數(shù)組nums={1,2,3,1}。
如果只有第0個(gè)房間,可能搶也可能不搶。但這基本是廢話(huà),不搶顯然拿不到價(jià)值。
  搶,得1,
  不搶得0。
  取最大值,得到的價(jià)值是1。
如果只有第0個(gè)和第1個(gè) 房間。對(duì)于房間1可能搶,也可能不搶。
  如果搶第1個(gè)房間,那得到的價(jià)值是2,因?yàn)榈?個(gè)房間不搶的價(jià)值是0。
  如果不搶第1個(gè)房間,那得到的價(jià)值是1,因?yàn)榈?個(gè)房間搶,得1,不搶得0,取最大值。Max(搶第1個(gè)房間,不搶第1個(gè)房間)=2。

如果只有第0個(gè)、第1個(gè) ,第2個(gè)房間。對(duì)于房間2可能搶,也可能不搶。
  如果不搶第2個(gè)房間,那最后拿到的價(jià)值就是Max(搶第1個(gè)房間,不搶第1個(gè)房間)=2。
  如果搶第2個(gè)房間,那最后拿到的價(jià)值就是不搶第1個(gè)房間的價(jià)值+nums[2]=1+3=4。
  那最大的答案是Max(不搶第2個(gè)房間,搶第2個(gè)房間)=4。
分析到這里我們知道在新增一個(gè)房間的時(shí)候與上一個(gè)房間的搶和不搶獲得的價(jià)值有關(guān)系。最后答案是在當(dāng)前房間號(hào)搶和不搶狀態(tài)取最大值。這樣基本上dp方程就出來(lái)了。

我們用dp[i]記錄第i個(gè)房間的狀態(tài),dp[i][0]表示第i個(gè)房間不搶的價(jià)值,dp[i][1]代表第i個(gè)房間搶后的價(jià)值。 dp[i][0]=max(dp[i-1][0],dp[i-1][1]) dp[i][1]=dp[i-1][0]+nums[i]

嗯,這就是我的思考方式,是從回溯算法開(kāi)始,不斷優(yōu)化,最后整理到dp,然后總結(jié)出dp應(yīng)該這樣思考。當(dāng)然還缺少一步是內(nèi)存優(yōu)化。只與上一步的狀態(tài)有關(guān)系,可以用變量表示,而無(wú)需數(shù)組。

public int robV4(int[] nums) {if(nums==null || nums.length==0) return 0;int n = nums.length;int v0 = 0 ,v1=nums[0];for(int i=1;i<n;i++){int tmp0 = Math.max(v0,v1);int tmp1 = v0+nums[i];v0=tmp0;v1=tmp1;}return Math.max(v0,v1);}

213 House Robber II

class Solution {public int rob(int[] nums) {if(nums==null || nums.length==0) return 0;if(nums.length==1) return nums[0];return Math.max(rob(nums,0,nums.length-2),rob(nums,1,nums.length-1));}public int rob(int[] nums,int start,int end) {int n = nums.length;int[][] dp = new int[2][n];dp[0][start] = nums[start];dp[1][start] = 0;for(int i=start+1;i<=end;i++){dp[0][i] = dp[1][i-1] + nums[i];dp[1][i] = Math.max(dp[0][i-1],dp[1][i-1]);}return Math.max(dp[0][end],dp[1][end]);} }

總結(jié)

以上是生活随笔為你收集整理的[dp]leetcode 198. House Robber的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。