打家劫舍(一)

题目

  • 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
  • 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
    1
    2
    3
    4
    示例1:
    输入:[1,2,3,1]
    输出:4
    解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。
    1
    2
    3
    4
    5
    示例2:
    输入:[2,7,9,3,1]
    输出:12
    解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
    偷窃到的最高金额 = 2 + 9 + 1 = 12 。

    解题思路

状态转移方程

  • 假设一排房屋rooms(房间数>2),从最右侧开始考虑,对于第i+1间房屋rooms[i]只有两种状态:
    1. 偷窃:最近的下一间可偷窃的房间就是[i-2],已获得金额rooms[i]
      • 最终获得金额:f(i-2) + rooms[i]
    2. 不偷窃:最近的下一间可偷窃的房间就是[i-1],已获得金额0
      • 最终获得金额:f(i-1) + 0
  • 所以最终能得到的最高金额就是:
    1
    result = Max((f(i-2) + rooms[i]),f(i-1))

考虑边界值

  • 房屋数为0: result = 0;
  • 房屋数为1: result = rooms[0];

输出

  • 判断输出是否为最终状态;

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Solution {

public static HashMap<Integer, Integer> cache = new HashMap<>();
public static int rob(int[] rooms) {
cache.clear();
return fCore(rooms, rooms.length - 1);
}

public static int fCore(int[] rooms, int index) {
if (index < 0) {
return 0;
}
if (index == 0) {
return rooms[0];
}
if (cache.containsKey(index)) {
return cache.get(index);
}

int count = Math.max(fCore(rooms, index - 1), fCore(rooms, index - 2) + rooms[index]);
cache.put(index, count);
return count;
}
}

打家劫舍(二)

题目

  • 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈, 这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
  • 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下 ,能够偷窃到的最高金额。

解题思路

  • 状态转移方程和基本思路同打家劫舍(一),
  • 环状排列意味着第一个房子和最后一个房子中只能选择一个偷窃,因此可以把此环状排列房间问题约化为两个单排排列房间子问题:
    1. 在不偷窃第一个房子的情况下(rooms[1 ~ n]),最大金额是P1;
    2. 在不偷窃最后一个房子的情况下(rooms[0 ~ (n-1)]),最大金额是P2。
  • 比较两者较大值max(p1, p2)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public static HashMap<Integer, Integer> cache = new HashMap<>();
public int rob(int[] nums) {
if(nums.length == 1) return nums[0];
cache.clear();
int max1 = myRob(Arrays.copyOfRange(nums, 0, nums.length - 1), nums.length-2);
cache.clear();
int max2 = myRob(Arrays.copyOfRange(nums, 1, nums.length), nums.length-2);
return Math.max(max1, max2);
}
private int myRob(int[] rooms, int index) {
if (index < 0) {
return 0;
}
if (index == 0) {
return rooms[0];
}
if (cache.containsKey(index)) {
return cache.get(index);
}
int count = Math.max( myRob(rooms, index - 1), myRob(rooms, index - 2) + rooms[index]);
cache.put(index, count);
return count;
}
}