leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 55 】2021-11-03 - 198. 打家劫舍 #74

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

198. 打家劫舍

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/house-robber/

前置知识

暂无

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

 

示例 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 。
 

提示:

0 <= nums.length <= 100
0 <= nums[i] <= 400
ychen8777 commented 2 years ago

思路

DP + 记忆化搜索\ 创建新 array, array[i] 记录到达第 i 户时的最高金额

代码

class Solution {
    public int rob(int[] nums) {

        if (nums.length == 1) {
            return nums[0];
        }

        int[] reward = new int[nums.length];
        reward[0] = nums[0];
        reward[1] = Math.max(reward[0], nums[1]);

        for(int i = 2; i < nums.length; i++) {
            reward[i] = Math.max(reward[i-1], reward[i-2]+nums[i]);
        }

        return reward[nums.length-1];

    }
}

复杂度

时间: O(n) \ 空间: O(n)

JK1452470209 commented 2 years ago

思路

每次选取dp[i]状态取决于前一个dp[i-1]与前前一个dp[i-2]加上num[i-2]最大值

代码

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

复杂度

时间复杂度:O(N)

空间复杂度:O(N)

chakochako commented 2 years ago
def rob(self, nums: List[int]) -> int:
    prev = 0
    curr = 0

    for i in nums:
        prev, curr = curr, max(curr, prev + i)

    return curr
AgathaWang commented 2 years ago
class Solution:
    def rob(self, nums: List[int]) -> int:
        # 动态规划
        # method 1:
        # tc: O(N)  sc: O(N)
        len_n = len(nums)
        if len_n == 0:
            return 0
        if len_n == 1:
            return nums[0]

        dp = [0] * len_n
        dp[0] = nums[0]  # 只有一间房屋
        dp[1] = max(nums[0],nums[1])  #只有两件房屋
        #不打劫第i间房和打劫第i间房中的较大值 - 转移方程
        for i in range(2,len_n):
            dp[i] = max(dp[i-2]+nums[i],dp[i-1])
        return dp[len_n-1]
ghost commented 2 years ago

题目

  1. House Robbery

思路

DP

代码

class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) < 2: return max(nums)

        preA = nums[0]
        preB = res = max(nums[0], nums[1])

        for i in range(2, len(nums)):
            res = max(preA+nums[i], preB)

            preA, preB = preB, res

        return res

复杂度

Space: O(1) Time: O(n)

dongzegithub commented 2 years ago

    // 暴力递归
    public int rob1(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        return rob1(nums, nums.length - 1);
    }

    private int rob1(int[] nums, int i) {
        if (i == 0) {
            return nums[0];
        }
        if (i == 1) {
            return Math.max(nums[0], nums[1]);
        }
        return Math.max(rob1(nums, i - 1), rob1(nums, i - 2) + nums[i]);
    }

    // 动态规划
    public int rob(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int length = nums.length;
        if (length == 1) {
            return nums[0];
        }

        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < length; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }

        return dp[length - 1];
    }
pan-qin commented 2 years ago

Idea:

dp. At house i, if rob it, the next available house is i+2; if not rob it, next available house i+1. Innitialize a dp[] array to store the maximum money we can get by robbing from house i.

Complexity:

Time: O(n) Space: O(n)

class Solution {
    public int rob(int[] nums) {
        int[] dp = new int[nums.length+2];
        for(int i=nums.length-1;i>=0;i--) {
            dp[i]=Math.max(nums[i]+dp[i+2], dp[i+1]);
        }
        return dp[0];

    }
}
15691894985 commented 2 years ago

【Day 55】198. 打家劫舍

https://leetcode-cn.com/problems/house-robber/

思路:解决第[i]个房子抢还是不抢的问题,抢的化:当前价值+dp[i-2],因为i-1不能抢,不抢就是dp[i-2]

dp[i]=max(dp[i-1],dp[i-2]+num[i-2]) 令dp[0]=dp[1]=0所以当前i价值等于num[i-2[] 这就是第一个决策的房子

class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        dp = [0]*(len(nums)+2)
        for i in range(2,len(nums)+2):
            dp[i] = max(dp[i-1],dp[i-2]+nums[i-2])
        return dp[len(nums)+1]

复杂度分析:

时间复杂度:O(n)遍历num

空间复杂度:O(n) 记录dp状态

由于只需要保留dp[i-1],dp[i-2]两个状态,考虑滚动数组:

class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        else:
            pre = nums[0]
            cur = max(pre,nums[1])
            for i in range(2,len(nums)):
                cur, pre = max(pre + nums[i],cur),cur
        return cur

空间复杂度:O(1)

shixinlovey1314 commented 2 years ago

Title:198. House Robber

Question Reference LeetCode

Solution

Since we can't take two adjacent values, when buiding the solution, we could try to skip 1 or 2 values, but no need to more than 3 values (instead of skiping 3, we could just take the one in the middle and still satisfy the constraint.) Let dp[i] be the maximum total value we could get at index i, we know that dp[i] = nums[i] + max(dp[i-2], dp[i-3]).

Code

class Solution {
public:
    int rob(vector<int>& nums) {
        if (!nums.size())
            return 0;
        if (nums.size() == 1)
            return nums[0];

        int n = nums.size();
        vector<int> dp (n, 0);
        dp[0] = nums[0];
        dp[1] = nums[1];

        for (int i = 2; i < n; i++)
            dp[i] = nums[i] + ((i < 3) ? dp[i - 2] : max (dp[i - 2], dp[i - 3]));

        return max(dp[n-1], dp[n-2]);
    }
};

Complexity

Time Complexity and Explanation

O(n)

Space Complexity and Explanation

O(n)

nonevsnull commented 2 years ago

思路

AC

代码

//从左往右想,从右往左推,top-down,递归
class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n+2];
        int res = 0;
        for(int i = n + 1;i >= 2;i--){
            dp[i - 2] = Math.max(nums[i - 2] + dp[i], res);
            res = dp[i - 2];
        }

        return res;
    }
}

复杂度

time: O(N),遍历每个step space: O(N),都需要,存储dp值,其实可以优化到O(1),因为每一次都只是想知道next.next的值,而不是全部。

akxuan commented 2 years ago

直接dp 时见复杂度 O(N) 空间1 状态压缩

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        # 用 robber 当 dp
        # 

        rob, not_rob = 0, 0
        for idx in range(len(nums)):
            num = nums[idx]
            rob, not_rob = not_rob + num, max(rob, not_rob)
        return max(rob, not_rob)
yuxiangdev commented 2 years ago
 public int rob(int[] nums) {
        if (nums == null) return 0;
        int n = nums.length;
        if (n == 0) return 0;
        if (n == 1) return nums[0];
        int[] dp = new int[n];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < n; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }
        return dp[n - 1];
    }
Complexity Time O(n) | Space O(n)
biscuit279 commented 2 years ago

思路:求max(dp[i-2]+nums[i],dp[i-1])

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        dp = [0] * n
        if n<=2:
            return max(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0],nums[1])
        for i in range(2,n): 
            dp[i] = max(dp[i-2]+nums[i],dp[i-1])
        return dp[-1]

时间复杂度:O(N) 空间复杂度:O(N)

TimmmYang commented 2 years ago

思路

动态规划。dp[i] = max(dp[i−2]+nums[i], dp[i−1]),使用两个变量即可。

代码

class Solution:
    def rob(self, nums: List[int]) -> int:
        prev, curr = 0, 0
        for num in nums:
            prev, curr = curr, max(prev + num, curr)
        return curr

复杂度

时间:O(n) n为nums长度 空间:O(1)

KennethAlgol commented 2 years ago

class Solution {
    public int rob(int[] nums) {
        int count = 0;
        if(nums.length == 0){
            return 0;
        }
        if(nums.length == 1){
            return nums[0];
        }
        int[] s = new int[nums.length];
        s[0] = nums[0];
        s[1] = Math.max(nums[0],nums[1]);
        for(int i=2; i< nums.length; i++){
            s[i] = Math.max(s[i-1], s[i-2]+nums[i]);
        }
        return s[nums.length-1];
    }
}
leolisgit commented 2 years ago

题目

https://leetcode.com/problems/house-robber/

思路

注意对DP数组的定义。dp[i]表示经过第i家的最大收益,可以抢劫第i家也可以不抢。

代码

class Solution {
    public int rob(int[] nums) {
        if (nums.length == 1) {
            return nums[0];
        }

        int[] dp = new int[nums.length + 1];
        dp[0] = 0;
        dp[1] = nums[0];

        for (int i = 2; i <= nums.length; i++) {
            dp[i] = Math.max(dp[i - 2] + nums[i - 1], dp[i - 1]);
        }

        return dp[nums.length];
    }
}

复杂度

时间:O(n)
空间:O(n)

falconruo commented 2 years ago

思路:

方法一、 DP题,使用两个变量second, first代表截止到第i - 1个房子和第i-2个房子时偷盗的钱数,对于第i个房子有两种状态:

完成第i个房子时的总钱数= max(偷, 不偷)

复杂度分析:

代码(C++):

方法一、
class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();

        if (n == 0) return 0;
        if (n == 1) return nums[0];

        int first = nums[0];
        int second = max(nums[1], nums[0]);

        for (int i = 2; i < n; ++i) {
            int t = second;
            second = max(second, first + nums[i]);
            first = t;
        }

        return second;
    }
};
siyuelee commented 2 years ago
class Solution(object):
    def rob(self, nums):
        if not nums:
            return 0
        length = len(nums)
        if length == 1:
            return nums[0]

        dp = [0 for _ in range(length)]
        for i in range(length):

            if i == 0:
                dp[i] = nums[0]
            elif i == 1:
                dp[i] = max(dp[0], nums[1])
            else:
                dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
        return dp[-1]

T: O(N) S: O(N)

class Solution(object):
    def rob(self, nums):
        if not nums:
            return 0
        length = len(nums)
        if length == 1:
            return nums[0]

        prev = nums[0]
        cur = max(prev, nums[1])
        for i in range(2, length):
            temp = cur
            cur = max(prev + nums[i], cur)
            prev = temp
        return cur

T: O(N) S: O(1)

ysy0707 commented 2 years ago

思路:动态规划+空间优化

class Solution {
    //滚动数组优化空间
    public int rob(int[] nums) {
        int n = nums.length;
        // 处理边界条件
        if(n == 0){
            return 0;
        }
        if(n == 1){
            return nums[0];
        }
        //滚动递推
        int pre = nums[0];
        int cur = Math.max(nums[0],nums[1]);
        for(int i = 2; i < n; i++ ){
            int tmp = cur;
            cur = Math.max(cur, pre + nums[i]);
            pre = tmp;

        }
        return cur;
    }
}

时间复杂度:O(N) 空间复杂度:O(1)

ZhuMengCheng commented 2 years ago

JavaScript

/**
 * https://leetcode-cn.com/problems/house-robber/
 * @param {number[]} nums
 * @return {number}
 */
var rob = function (nums) {
    if (nums.length == 1) {
        return nums[0]
    } else if (nums.length == 2) {
        return Math.max(nums[0], nums[1])
    }
    let first = nums[0] // 定义最大值 奇数值和(下标)
    let second = Math.max(nums[0], nums[1]); // 定义最大值 偶数值和(下标)
    for (let i = 2; i < nums.length; i++) {
        let temp = second;
        // 首先存储当前后一位值,可能是奇数
        // 可能是偶数.交替往前相加判断,判断后的值,一直取最大值.获取到的最大值,可能是跨度超过2的最大值.
        second = Math.max(first + nums[i], second);
        // 保留当前相加比较前的下标的最大值
        first = temp;
    }
    return second;
};

// 时间复杂度 O(N) // 空间复杂度 O(1)

console.log(rob([1, 2, 3, 1])) // 4 console.log(rob([1, 2, 3, 1, 5, 4, 2, 6])) // 15

ai2095 commented 2 years ago

198. House Robber

https://leetcode.com/problems/house-robber/

Topics

思路

DP

代码 Python

class Solution:
    def rob(self, nums: List[int]) -> int:
        dp = [0] * 3
        for i in range(0, len(nums)):
            if i > 1:
                dp[i%3] = max(dp[i%3-2] + nums[i], dp[i%3-1])
            elif i == 0:
                dp[i] = nums[0]
            else:
                dp[i] = max(nums[i-1], nums[i])
        return dp[len(nums)%3-1]

复杂度分析

时间复杂度: O(N)
空间复杂度:O(1)

Zhang6260 commented 2 years ago

JAVA版本

思路:该题的是使用动态规划来完成,来到每一个房间都有偷和不偷二种选择,偷当前的房间就不能偷前一间,于是动态转移方程就为:dp[i] = Math.max(num[i-1]+dp[i-2],dp[i-1]);(因为当前房间的状态也只和前二个房间的状态相关,所以也可以直接继续空间压缩,直接只使用二个变量来存储。)

class Solution {
   public int rob(int[] nums) {
       if(nums==null||nums.length==0)return 0;
       int dp[] = new int[nums.length+1];
       dp[0]=0;
       for(int i=1;i<=nums.length;i++){
           //当前的房间偷了不偷这二种情况
           if(i==1){
               dp[i]=nums[i-1];
           }else{
               dp[i]=Math.max(nums[i-1]+dp[i-2],dp[i-1]);
           }

       }
       return dp[nums.length];
   }
}

时间复杂度:O(n)

空间复杂度:O(n)

Yufanzh commented 2 years ago

Intuition

DP approach\ dp[i] = max(dp[i-1], dp[i-2] + nums[i])\ In that case, will need to deal with edge cases: when len(nums) == 0 or len(nums) == 1

Algorithm in python3

class Solution:
    def rob(self, nums: List[int]) -> int:
        #dp[i] = max(dp[i-1], dp[i-2] + nums[i])
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        dp = [0]*len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2, len(nums)):
            dp[i] = max(dp[i-1], dp[i-2] + nums[i])
        return dp[-1]

Complexity Analysis

itsjacob commented 2 years ago

Intuition

Implementation

class Solution
{
public:
  int rob(vector<int> &nums)
  {
    if (nums.size() == 1) return nums[0];
    std::vector<int> dp(nums.size(), 0);
    dp[0] = nums[0];
    dp[1] = std::max(nums[0], nums[1]);
    for (int ii = 2; ii < dp.size(); ii++) {
      dp[ii] = std::max(dp[ii - 1], dp[ii - 2] + nums[ii]);
    }
    return dp[nums.size() - 1];
  }
};

Complexity

Leonalhq commented 2 years ago

思路

DP,两种状态偷/不偷

只需要-1和-2的状态,不需要存之前的

看了答案似乎可以优化空间,之后看一下

算法

def rob(self, nums):

​   if not nums:

​       return 0

​   maxRob = [0]*len(nums+1)

​   N = len(nums)

   maxRob[N], maxRob[N-1]=0,nums[N-1]

  for i in range(N-2,-1,-1):

​       maxRob[i] = max(maxRob[i+1],maxRob[i+2]+nums[i])

return maxRob[0]

复杂度:

时间

O(N)

空间

O(N)

suukii commented 2 years ago

Link to LeetCode Problem

S1: 动态规划

class Solution {
public:
    int rob(vector<int>& nums) {
        // dp[i] 表示当小偷来到第 i 间房子时,能偷到的最高金额
        int n = nums.size();
        vector<int> dp(n, 0);
        dp[0] = nums[0];
        for (int i = 1; i < n; i++) {
            // 1. 偷这个房子
            int a = (i - 2 >= 0 ? dp[i - 2] : 0) + nums[i];
            // 2. 不偷这个房子
            int b = dp[i - 1];
            dp[i] = max(a, b);
        }
        return dp[n - 1];
    }
};

S2: 动态规划(空间优化)

class Solution {
public:
    int rob(vector<int>& nums) {
        // dp[i] 表示当小偷来到第 i 见房子时,能偷到的最高金额
        int n = nums.size();
        int p1 = 0, p2 = 0;
        for (int i = 1; i < n; i++) {
            // 1. 偷这个房子
            int a = p1 + nums[i];
            // 2. 不偷这个房子
            int b = p2;
            p1 = p2;
            p2 = max(a, b);
        }
        return p2;
    }
};
chenming-cao commented 2 years ago

解题思路

动态规划。用maxAmt[i]来记录选择第i个房子作为最后偷窃的房子时能偷窃到的最高金额,那么在第i个房子之前,小偷只能偷第(i - 2)或者(i - 3)个房子,状态转移方程为maxAmt[i] = max(maxAmt[i - 3] + nums[i], maxAmt[i - 2] + nums[i]),其中i > 2。最后返回的结果考虑偷不偷最后房子,可以为maxAmt[n - 1](偷)或者maxAmt[n - 2](不偷),返回最大值即可。对于i = 1和i = 2我们分别讨论,i = 1时为nums[0], i = 2时为max(nums[0], nums[1])。

代码

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        // base cases
        if (n == 1) return nums[0];
        if (n == 2) return Math.max(nums[0], nums[1]);
        // use an array to store the maxAmt when robbing the ith house as the last one
        int[] maxAmt = new int[n];
        // inital states, when n >= 3
        maxAmt[0] = nums[0];
        maxAmt[1] = nums[1];
        maxAmt[2] = nums[0] + nums[2];
        for (int i = 3; i < n; i++) {
            // if the ith house is to be robbed, then (i-1)th house must not be robbed. Only choices are robbing (i - 2)th house or (i - 3)th house as previous last house, because they are not adjacent to the ith house
            maxAmt[i] = Math.max(maxAmt[i - 3] + nums[i], maxAmt[i - 2] + nums[i]);
        }
        // the maximum amount could be either choosing the last house or the second last house as the last robbing target
        return Math.max(maxAmt[n - 2], maxAmt[n - 1]);
    }
}

复杂度分析

chaggle commented 2 years ago

title: "Day 55 198. 打家劫舍" date: 2021-11-03T13:26:11+08:00 tags: ["Leetcode", "c++", "DP"] categories: ["91-day-algorithm"] draft: true


198. 打家劫舍

题目

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

 

示例 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 。
 

提示:

1 <= nums.length <= 100
0 <= nums[i] <= 400

题目思路

  • 1、dp是原来掌握最熟练的部分,但是由于好久没分析状态方程了,居然错了许多次。
  • 2、把握好状态方程即可解决问题,分析为dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
  • 3、故优化空间后,跟fib一样只需要维护两个空间即可。
class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if(n == 1) return nums[0];
        if(n == 2) return max(nums[0], nums[1]);
        int dp[2];
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for(int i = 2; i < n; i++)
        {
            int best = max(dp[0] + nums[i], dp[1]);
            dp[0] = dp[1];
            dp[1] = best;
        }

        return dp[1];
    }
};

复杂度

q815101630 commented 2 years ago

先打卡,明天补

class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        if len(nums) == 1:
            return nums[0]
        dp = [0]*len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2, len(nums)):
            dp[i] = max(dp[i-1], dp[i-2]+nums[i])

        return dp[-1]
chen445 commented 2 years ago

思路

Solution1: We keep track of two variables. One is the max when we rob the house, the other one is the max when we don't rob the house.

Solution2: At each index, we have two choice, either we rob the house or we don't rob the house. We recursively compute the max amount for both choices. And we pick the max one.

代码

Solution1

class Solution:
    def rob(self, nums: List[int]) -> int:
        inclusive, exclusive = 0, 0
        for n in nums:
            inclusive, exclusive = n+exclusive, max(inclusive,exclusive)
        return max(inclusive, exclusive)

Solution2

class Solution:
    def rob(self, nums: List[int]) -> int:
        memo={}
        def dfs(current_position):
            if current_position>=len(nums):
                return 0

            if current_position+2 in memo:
                amount1=memo[current_position+2]+nums[current_position]
            else:
                amount1=dfs(current_position+2)+nums[current_position]

            if current_position+1 in memo:
                amount2=memo[current_position+1]
            else:
                amount2=dfs(current_position+1)
            memo[current_position]=max(amount1,amount2)
            return memo[current_position]
        return dfs(0)

复杂度

Solution1

Time: O(n)

Space: O(1)

Solution2

Time: O(n)

Space: O(n)

qyw-wqy commented 2 years ago
class Solution {
    public int rob(int[] nums) {
        int rob = nums[0]; 
        int notRob = 0;
        for (int i = 1; i < nums.length; i++) {
            int temp = rob;
            rob = Math.max(rob, notRob + nums[i]);
            notRob = Math.max(notRob, temp);
        }
        return Math.max(rob, notRob);
    }
}

Time: O(n)\ Space: O(1)

weichuliao commented 2 years ago
class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0

        length = len(nums)
        if length == 1:
            return nums[0]
        else:
            prev = nums[0]
            cur = max(prev, nums[1])
            for i in range(2, length):
                cur, prev = max(prev + nums[i], cur), cur
            return cur
Daniel-Zheng commented 2 years ago

思路

动态规划。

代码(C++)

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.empty()) {
            return 0;
        }
        int size = nums.size();
        if (size == 1) {
            return nums[0];
        }
        vector<int> dp = vector<int>(size, 0);
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for (int i = 2; i < size; i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[size - 1];
    }
};

复杂度分析

xyinghe commented 2 years ago
class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0

        n = len(nums)
        if n == 1:
            return nums[0]

        dp = [0] * n 
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2,n):
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])

        return dp[n-1]
learning-go123 commented 2 years ago

思路

关键点

代码

Go Code:


func rob(nums []int) int {
    if len(nums) == 1 {
        return nums[0]
    }
    nums[1] = max(nums[0], nums[1])
    for i := 2; i < len(nums); i++ {
        nums[i] = max(nums[i-2]+nums[i], nums[i-1])
    }

    return max(nums[len(nums)-2], nums[len(nums)-1])
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

复杂度分析

令 n 为数组长度。

watermelonDrip commented 2 years ago
class Solution:
    def rob(self, nums: List[int]) -> int:
        dp = [0]*(len(nums)+1)
        if len(nums) == 1:
            return nums[0]
        if len(nums) == 2:
            return max(nums)

        dp[0] = nums[0]

        for i in range(1,len(nums)):
            # i choose
            tmp1 = dp[i-2] + nums[i]
            # not choose i
            tmp2 = dp[i-1]
            dp[i] = max(tmp1,tmp2)

        return max(dp)
jiahui-z commented 2 years ago

思路: iterate through the number, maintain the maximum money we can get so far

class Solution {
    public int rob(int[] nums) {
        if (nums.length == 1) {
            return nums[0];
        }

        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);

        for (int i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1]);
        }

        return dp[nums.length-1];
    }
}

Time Complexity: O(n) Space Complexity: O(n)

doveshnnqkl commented 2 years ago

思路

动态规划

代码

java

class Solution {
    public int rob(int[] nums) {
         int len = nums.length;
         int[] dp = new int[len];
         if(len == 1){
             return nums[0];
         }else if(len == 2){
             return Math.max(nums[0], nums[1]);

         }
         dp[0] = nums[0];
         dp[1] = Math.max(nums[0],nums[1]);
         for(int i = 2; i < len; i++){
            dp[i] = Math.max(nums[i] + dp[i - 2],dp[i-1]);
         }
         return dp[len -1];
    }
}

复杂度

时间复杂度:O(n) 空间复杂度:O(n)

user1689 commented 2 years ago

题目

https://leetcode-cn.com/problems/house-robber/

思路

类二进制枚举, DP

python3

class Solution:
    def rob(self, nums: List[int]) -> int:
        # 二进制枚举
        maxMoney = 0
        @lru_cache(None)
        def dfs(idx, money, prev):
            nonlocal maxMoney

            if money > maxMoney:
                maxMoney = money

            if idx == len(nums):
                return 

            if prev != 1:
                dfs(idx + 1, money + nums[idx], 1)
            dfs(idx + 1, money, 0)

        dfs(0, 0, 0)
        return maxMoney

class Solution:

    def rob(self, nums: List[int]) -> int:
        # 二进制枚举
        dic = dict()

        def dfs(idx):            
            if idx >= len(nums):
                return 0

            if idx in dic:
                return dic[idx]
            # 分两种情况
            # 1.偷第start个房子,然后只能从第start+2个房子开始偷
            headFirst = nums[idx]
            headFirst += dfs(idx + 2)

            # 2.不偷第start个房子,从第start+1个房子偷
            noFirst = 0
            noFirst += dfs(idx + 1)
            # 取两种情况的最大值
            ans = max(headFirst, noFirst)
            dic[idx] = ans 
            return ans

        return dfs(0)

class Solution:
    def rob(self, nums: List[int]) -> int:
        # DP
        if not nums:
            return 0

        if len(nums) == 1:
            return nums[0]

        dp = [0] * (len(nums) + 1)
        dp[0] = 0
        dp[1] = nums[0]
        for i in range(2, len(nums) + 1):
            dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1])
        return dp[-1]

复杂度分析

相关题目

  1. https://leetcode-cn.com/problems/house-robber-ii/
  2. https://leetcode-cn.com/problems/house-robber-iii/
ginnydyy commented 2 years ago

Solution

todo

simonsayshi commented 2 years ago
class Solution {
public:
    int rob(vector<int>& nums) {
        vector<int> dp(nums.size(),0);
        if(nums.size() <=2){
            return *max_element(nums.begin(),nums.end());
        }
        for(int i = 0; i < nums.size();i++) {
            if(i == 0)
                dp[i] = nums[i];
            else if(i == 1) {
                dp[i] =  max(nums[0], nums[1]);
            }
            else
                dp[i] = max(dp[i - 1], dp[i-2] + nums[i]);
        }
        return dp.back();
    }
};
sxr000511 commented 2 years ago

class Solution { public: int rob(vector& nums) { if (nums.empty()) { return 0; } int size = nums.size(); if (size == 1) { return nums[0]; } vector dp = vector(size, 0); dp[0] = nums[0]; dp[1] = max(nums[0], nums[1]); for (int i = 2; i < size; i++) { dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); } return dp[size - 1]; } };

RonghuanYou commented 2 years ago

class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0

        pre1, pre2 = 0, 0

        for num in nums:
            temp = pre1
            pre1 = max(pre2 + num, pre1)
            pre2 = temp
        return pre1
asterqian commented 2 years ago

思路

题意就是不能打劫相邻的两间屋子。数组应该记录下当前位置能打劫到的最多的金额,那么就应该是either前一个index的值(即不打劫当前屋子)和再前一个index的值加当前屋子的金额(即不打劫前一间屋子)取最大值。因此需要initialize memo[0] memo[1]两个位置的值分别为num[0]和max(num[0],mum[1]),因为两间屋子不能同时打劫,选最大的。

代码

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.empty()) return 0;
        if (nums.size() == 1) return nums[0];
        vector<int> memo(nums.size());
        memo[0] = nums[0];
        memo[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size(); ++i) {
            memo[i] = max(memo[i - 1], memo[i - 2] + nums[i]);
        }
        return memo.back();
    }
};

Time Complexity: O(n)

Space Complexity: O(n)

m-z-w commented 2 years ago
var rob = function(nums) {
    const dp = []
    dp[0] = nums[0]
    dp[1] = Math.max(dp[0], nums[1])
    for (let i = 2; i < nums.length; i++) {
        dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1])
    }
    return dp[nums.length - 1]
};

时间:O(n) 空间:O(n)

hellowxwworld commented 2 years ago
int rob(vector<int>& nums) {
    int dp[nums.size()];
    dp[0] = nums[0];
    dp[1] = max(nums[0], nums[1]);

    for (int i = 2; i < nums.size(); ++i) {
        dp[i] = max(dp[i-2]+nums[i], dp[i-1]);
    }

    return dp[nums.size()-1];
}
ZJP1483469269 commented 2 years ago

题目地址(198. 打家劫舍)

https://leetcode-cn.com/problems/house-robber/

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

 

示例 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 。

 

提示:

1 <= nums.length <= 100
0 <= nums[i] <= 400

前置知识

公司

思路

动态规划

关键点

代码

Java Code:


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

复杂度分析

令 n 为数组长度。

kennyxcao commented 2 years ago

198. House Robber

Intuition

Code

/**
 * @param {number[]} nums
 * @return {number}
 */
const rob = function(nums) {
  let includePrev = 0;
  let excludePrev = 0;
  for (const num of nums) {
    const includeCurr = excludePrev + num;
    const excludeCurr = Math.max(excludePrev, includePrev);
    includePrev = includeCurr;
    excludePrev = excludeCurr;
  }
  return Math.max(includePrev, excludePrev);
};

Complexity Analysis

LareinaWei commented 2 years ago

Thinking

DP problem. Using an array dp to record the maximum value that could be robbed at ith house.
Since we cannot rob two houses in a row, there are two choices at house i:
(1) Rob the i - 1th house and do not rob the current house.
(2) Rob the i - 2th house and rob the current house.
Thus dp[i] = max(dp [i-1], dp[i-2] + value[I])

Code

class Solution:
    def rob(self, nums: List[int]) -> int:
        l = len(nums)
        if not nums:
            return 0
        if l == 1:
            return nums[0]
        if l == 2:
            return max(nums[0], nums[1])

        dp = [0 for _ in range(l)]
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])

        for i in range(2, l):
            dp[i] = max(dp[i-1], dp[i - 2] + nums[i])

        return dp[-1]

Complexity

Time complexity: O(n).
Space complexity: O(n).

carterrr commented 2 years ago
class 打家劫舍_198 {
    public int rob(int[] nums) {
        int length = nums.length;
        if(length == 1) return nums[0];
        if(length == 2) return Math.max(nums[0], nums[1]);
        int[] dp = new int[length];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for(int i = 2; i< length; i++ ) { // 状态转移方程   :  只取前一个的状态  和前一个的前一个加上自身  最大的
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }
        return Math.max(dp[length - 1], dp[length - 2]);
    }
}