Leetcode198——House Robber

探讨了在特定约束条件下,如何通过不同算法求解打家劫舍问题以获得最大收益。介绍了递归法、递归加缓存、非递归及使用数组优化等四种方法,并对比了它们的时间复杂度和空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章作者:Tyan
博客:noahsnail.com  |  CSDN  |  简书

1. 问题描述

ou are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

2. 求解

方法一递归法

递归法如下图所示,从第0家开始,偷与不偷有两种情况,如果偷了则从第2家开始重复此过程,如果没偷,从第1家开始重复此过程,直至结束。

递归过程

public class Solution {

    public int rob(int[] nums) {
        if(nums.length == 0) {
            return 0;
        }
        return robot(0, nums);
    }

    public int robot(int start, int[] nums) {
        if(start >= nums.length) {
            return 0;
        }
        int left = nums[start] + robot(start + 2, nums);
        int right = 0 + robot(start + 1, nums);
        int max = Math.max(left, right);
        return max;
    }
}

Leetcode运行超时,说明存在优化空间。

方法二递归法+缓存

从图中可以看出,上述过程中会有重复的计算,例如从第二家开始偷的情况计算了两次,我们可以用一个HashMap将计算过的数据保存起来,去掉冗余计算。

public class Solution {
    public static Map<Integer, Integer> cache = new HashMap<Integer, Integer>();

    public int rob(int[] nums) {
        cache.clear();
        if(nums.length == 0) {
            return 0;
        }
        return robot(0, nums);
    }

    public int robot(int start, int[] nums) {
        if(start >= nums.length) {
            return 0;
        }
        if(cache.containsKey(start)) {
            return cache.get(start);
        }
        int left = nums[start] + robot(start + 2, nums);
        int right = 0 + robot(start + 1, nums);
        int max = Math.max(left, right);
        cache.put(start, max);
        return max;
    }
}

方法三:非递归

将递归改造成非递归。

public class Solution {
    public static Map<Integer, Integer> cache = new HashMap<Integer, Integer>();

    public int rob(int[] nums) {
        cache.clear();
        if(nums.length == 0) {
            return 0;
        }
        int n = nums.length;
        cache.put(n-1, nums[n - 1]);
        for(int i = n - 2; i >=0; i--) {
            int a = nums[i] + (cache.containsKey(i + 2) ? cache.get(i + 2) : 0);
            int b = cache.containsKey(i + 1) ? cache.get(i + 1) : 0;
            int max = Math.max(a, b);
            cache.put(i, max);
        }
        return cache.get(0);
    }
}

**方法四:**HashMap变为数组

为了节省空间,可以将HashMap变为数组,代码也可以进一步优化,去掉三目运算符。

public class Solution {
    public int rob(int[] nums) {
        if(nums.length == 0) {
            return 0;
        }
        if(nums.length == 1) {
            return nums[0];
        }
        if(nums.length == 2) {
            return Math.max(nums[0], nums[1]);
        }
        int n = nums.length;
        int[] cache = new int[n];
        cache[n - 1] = nums[n - 1];
        cache[n - 2] = Math.max(nums[n - 1], nums[n - 2]);
        for(int i = n - 3; i >=0; i--) {
            cache[i] = Math.max(nums[i] + cache[i + 2], cache[i + 1]);
        }
        return cache[0];
    }   
}
### 力扣热门100题列表 力扣(LeetCode)上的热门题目通常是指那些被广泛讨论、高频面试或者具有较高难度的题目。这些题目涵盖了数据结构和算法的核心知识点,适合用来提升编程能力和解决实际问题的能力。 以下是基于社区反馈整理的部分 **LeetCode Hot 100 Problems List**: #### 数组与字符串 1. Two Sum (两数之和)[^1] 2. Longest Substring Without Repeating Characters (无重复字符的最长子串)[^2] 3. Median of Two Sorted Arrays (两个有序数组的中位数)[^1] 4. Container With Most Water (盛最多水的容器)[^2] #### 链表 5. Reverse Linked List (反转链表) 6. Merge Two Sorted Lists (合并两个有序链表) 7. Remove Nth Node From End of List (删除倒数第N个节点) 8. Linked List Cycle II (环形链表II) #### 堆栈与队列 9. Valid Parentheses (有效的括号) 10. Min Stack (最小栈) 11. Sliding Window Maximum (滑动窗口最大值)[^2] #### 树与二叉树 12. Binary Tree Inorder Traversal (二叉树的中序遍历) 13. Validate Binary Search Tree (验证二叉搜索树) 14. Same Tree (相同的树) 15. Serialize and Deserialize Binary Tree (序列化与反序列化二叉树) #### 图论 16. Number of Islands (岛屿数量) 17. Course Schedule (课程表) 18. Clone Graph (克隆图) #### 排序与搜索 19. Find First and Last Position of Element in Sorted Array (在排序数组中查找元素的第一个和最后一个位置) 20. Search a 2D Matrix (二维矩阵搜索) 21. K Closest Points to Origin (最接近原点的K个点) #### 动态规划 22. Climbing Stairs (爬楼梯) 23. House Robber (打家劫舍)[^1] 24. Coin Change (零钱兑换) 25. Unique Paths (不同路径) #### 贪心算法 26. Jump Game (跳跃游戏)[^1] 27. Non-overlapping Intervals (无重叠区间) 28. Best Time to Buy and Sell Stock (买卖股票的最佳时机)[^1] #### 字符串匹配与处理 29. Implement strStr() (实现strStr()) 30. Longest Consecutive Sequence (最长连续序列) 31. Group Anagrams (分组异位词) --- ### 示例代码片段 以下是一个关于动态规划的经典例子——`Climbing Stairs` 的 Python 实现: ```python class Solution: def climbStairs(self, n: int) -> int: if n == 1 or n == 2: return n dp = [0] * (n + 1) dp[1], dp[2] = 1, 2 for i in range(3, n + 1): dp[i] = dp[i - 1] + dp[i - 2] return dp[n] ``` 上述代码通过动态规划的方式解决了 `Climbing Stairs` 问题,时间复杂度为 \(O(n)\),空间复杂度同样为 \(O(n)\)[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值