Leecode刷題日記198-打家劫舍【Java】

打家劫舍

1.問題描述

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警

給定一個代表每個房屋存放金額的非負整數數組,計算你 不觸動警報裝置的情況下 ,一夜之內能夠偷竊到的最高金額。

示例 1:

輸入:[1,2,3,1]
輸出:4
解釋:偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
     偷竊到的最高金額 = 1 + 3 = 4 。

示例 2:

輸入:[2,7,9,3,1]
輸出:12
解釋:偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5 號房屋 (金額 = 1)。
     偷竊到的最高金額 = 2 + 9 + 1 = 12 。

2.思路

​ 2.1 第一眼看到這個問題,就會考慮到,每個房間都有選和不選兩種狀態,暴力至上,窮舉所有的狀態,並加入互不相鄰的限制條件,然後求所有方案的值,並選出最大值,時間複雜度爲 2^n.

​ 2.2 題目要求取最大的搶劫方案,考慮使用貪心算法,依次選取最大價值的財物,但是由於限制不能相鄰,不便使用該方法。

​ 2.3 考慮使用動態規劃。弄清楚以下問題:

​ 原問題:求取 n 個房間的最佳搶劫方案;

​ 子問題:求取前 i 個房間的最佳搶劫方案;

​ 狀態 :對前 i個房間,可以選擇搶 第 i 個房間和 i -2之前的房間,或者不搶它,搶前 i -1 個房間;

​ 邊界條件:dp[0] = nums[0];dp[1] = max(nums[0],nums[1]);

​ 狀態轉移方程:

​ 每個房間有選和不選兩個狀態,考慮前 i 個房間的方案,如果選擇了第 i 個房間,則一定不能選第 i - 1 個房間,那麼最佳方案轉化爲求 前 i - 2個房間的最佳方案加上 nums[i];如果不選第i個房間,那麼就可以選第 i - 1個房間的方案,即 dp[i] = Math.Max(dp[i-2]+nums[i],dp[i-1]),時間複雜度爲O(n).

3.解法

	 //0ms,100%
		public int rob(int[] nums) {
	        if(nums==null||nums.length==0)return 0;
	        int roomNums = nums.length;
	        if(roomNums==1) return nums[0];
	        if(roomNums==2)return Math.max(nums[0], nums[1]);
	        int[] dpResult = new int[roomNums];
	        dpResult[0] = nums[0];
	        dpResult[1] =  Math.max(nums[0], nums[1]);
	        for(int i = 2;i< roomNums;i++) {
	        	   dpResult[i] =  Math.max( dpResult[i-2]+nums[i],  dpResult[i-1]); // 選擇第i個房間,那麼只能選第i-2個房間之前的,或者不選房間i,那麼結果就是選i-1的方案
	        }
	      return dpResult[roomNums-1];
	    }

以上方法還可以對空間利用進行優化,不必拿一個數組專門存數據,充分利用中間結果賦值(來自leecode官方解法):

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章