LeetCode - 198. House Robber

来源:互联网 发布:安卓手机怎么查mac 编辑:程序博客网 时间:2024/06/03 13:20

每一个house都有rob和not rob两种状态,所以我们可以使用一个[n][2]的矩阵来记录每个房子被抢和不被抢的情况下所累计的钱的数量,这道动态规划问题的四要素如下:

state: f[i][0], f[i][1]记录某个房子被抢或者不被抢的情况下所累积的钱的数量

function: f[i][0] = max(f[i - 1][0], f[i - 1][1]),如果当前的房子不被抢,那么累计的钱是上一个房子被抢和不被抢两种情况下的最大值

                f[i][1] = nums[i] + f[i - 1][0],如果当前的房子被抢,那么累计的钱是当前房子的钱+上一个房子不被抢累计的钱

initialize:

answer: max(f[i][0], f[i][1])

这种解法的时间复杂度为O(n),空间复杂度为O(n),接下来我们考虑一下循环中的递进关系,我们可以使用三个变量:rob表示如果抢上一个房子所得到的钱,notRub表示不抢上一个房子所能得到的钱,currRob表示抢当前房子所能得到的钱进行不断循环迭代,从而将空间复杂度由O(n)降低至O(1)。两种写法的代码如下:

public class Solution {    public int rob(int[] nums) {        if(nums == null || nums.length == 0) return 0;      // corner case                int[][] dp = new int[nums.length][2];        // DP        for(int i = 1; i < nums.length; i++){            dp[i][0] = Math.max(dp[i - 1][1]), dp[i - 1][0]);            dp[i][1] = nums[i] + dp[i - 1][0];        }        return Math.max(dp[nums.length][0], dp[nums.length][1]);    }}// Optimized versionpublic class Solution {    public int rob(int[] nums) {        if(nums == null || nums.length == 0) return 0;      // corner case                int n = nums.length;        int rob = 0;        // money if rob        int notRob = 0;     // money if not rob                // DP        for(int i = 0; i < n; i++){            int currRob = notRob + nums[i];     // money if rob current house            notRob = Math.max(notRob, rob);     // money if not rob current house            rob = currRob;        }                return Math.max(rob, notRob);    }}


知识点:

1. 在做动态规划相关的问题的时候,首先不要去想怎样能够写出空间复杂度最小的解法,首先要去想怎样才能解决这个问题,然后根据解法中的递进关系来考虑可否对空间复杂度进行优化

2. 在动态规划是如果遇到与状态有关的问题,比如这道题每个房子都有被抢和不被抢两个状态,可以对每个状态分配空间

0 0