打家劫舍问题

简介: 打家劫舍问题

题目

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

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


实例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

解题思路

如果你是初次接触动态规划的问题,你只需要牢记一句话:“当前的结果都是由之前的过程推导出来的。”而不可以是先考虑后面的情况,因为后面的情况是未知的,我们只知道前面的结果,用已知求未知是关键。


①要把推导的过程列出来,从而知道当前结果是怎么推导出来的(画表格),

②根据表格规律,进而写出递推方程式

③找出base情况(即dp [i] 的基础情况,这道题的base情况就是数组中每个元素本身)

④根据方程式计算出 dp 中其他内容

当前金额是由(前一个的金额)或(当前金额加上除前一个金额外最大的金额)中大的那个构成

过leetcode代码如下(Java):

class Solution {
    public int rob(int[] num){
        int []dp = new int[num.length];
//      递推方程:dp[i] = max(dp[i-1] , dp[i]+max(dp[i-2]~dp[0]))
        for (int i = 0; i < num.length; i++) {
            dp[i] = num[i];
        }
        for (int i = 1; i < dp.length; i++) {
            int max = 0;
            for (int j = i - 2; j >= 0; j--) {
                if (dp[j] > max)
                    max = dp[j];
            }
            dp[i] = Math.max(dp[i - 1], dp[i] + max);
        }
        int max = 0;
        for (int j : dp) {
            if (j > max)
                max = j;
        }
        return max;
    }
}

过lanqiao代码如下(Java):

import java.util.Scanner;
public class Main {
    static int[] dp;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String line = scanner.nextLine();
        line = line.substring(1, line.length() - 1);
        String[] array = line.split(",");
        dp = new int[array.length];
//      递推方程:dp[i] = max(dp[i-1] , dp[i]+max(dp[i-2]~dp[0]))
        for (int i = 0; i < array.length; i++) {
            dp[i] = Integer.parseInt(array[i]);
        }
        for (int i = 1; i < dp.length; i++) {
            int max = 0;
            for (int j = i - 2; j >= 0; j--) {
                if (dp[j] > max)
                    max = dp[j];
            }
            dp[i] = Math.max(dp[i - 1], dp[i] + max);
        }
        int max = 0;
        for (int j : dp) {
            if (j > max)
                max = j;
        }
        System.out.println(max);
    }
}

总结

当我们初次接触到dp问题时,总是以最直观的方法进行求解,即先思考后面的情况如何规划,却没有想到后面的情况是不可预知的;应该仔细分析已知条件,从前面已知的条件入手,推导出当前这项的最优解,这也是动态规划的核心!

文章粗浅,希望对大家有帮助!

相关文章
|
1月前
|
存储
72. 编辑距离、198.打家劫舍、213_打家劫舍2(12021-11-06)
72. 编辑距离、198.打家劫舍、213_打家劫舍2(12021-11-06)
22 0
|
6月前
力扣337.打家劫舍3(树形dp)
力扣337.打家劫舍3(树形dp)
|
6月前
代码随想录 Day40 动态规划08 LeetCodeT198打家劫舍 T213打家劫舍II T337 打家劫舍III
代码随想录 Day40 动态规划08 LeetCodeT198打家劫舍 T213打家劫舍II T337 打家劫舍III
49 0
|
6月前
|
Java
leetcode-213:打家劫舍 II
leetcode-213:打家劫舍 II
40 0
|
6月前
|
Java
leetcode-337:打家劫舍 III
leetcode-337:打家劫舍 III
45 0
打家劫舍篇
打家劫舍篇
72 0
|
机器学习/深度学习 Cloud Native Go
337.打家劫舍 III:动态规划
这是力扣上的 337. 打家劫舍 III,难度为 中等。
leetcode 337 打家劫舍III
leetcode 337 打家劫舍III
83 0
leetcode 337 打家劫舍III
leetcode 213 打家劫舍II
leetcode 213 打家劫舍II
87 0
leetcode 213 打家劫舍II