打家劫舍题目的思路探讨与源码
打家劫舍的题目如下图,该题属于动态规划和数组类型的题目,主要考察对于动态规划和数组的使用理解和认识。本文的题目作者想到2种方法,分别是递归方法和动态规划方法,其中递归方法使用java进行编写,而动态规划方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
本人认为该题目可以使用递归的算法,首先我们获取数组的长度,并且初始化一个Map方便后续的存储。然后调用递归函数calMax方法,令下标等于最后一位,如果下标小于0则结束递归。首先判断Map里面有没有当前位置前两位的下标,如果有则最终值是当前位置前两位的值,否则的话就继续调用递归函数calMax,并且把当前位置前两位的值和下标记录下来,然后再去访问当前位置的前面一个位置和它的值,思路和前面一样,那么按照这个思路我们的Java代码如下:
#喷火龙与水箭龟
class Solution {
public int rob(int[] nums) {
Map<Integer,Integer> kv = new HashMap<>();
int len = nums.length-1;
return calMax(nums,len,kv);
}
public int calMax(int[] nums,int jr,Map<Integer,Integer> kv) {
if(jr<0)
return 0;
int finalNum = 0;
int maxNum = 0;
if (kv.containsKey(jr-2))
finalNum = kv.get(jr-2);
else {
finalNum = calMax(nums,jr-2,kv);
kv.put(jr-2,finalNum);
}
if (kv.containsKey(jr-1))
maxNum = kv.get(jr-1);
else {
maxNum = calMax(nums,jr-1,kv);
kv.put(jr-1,maxNum);
}
int index = finalNum + nums[jr];
return Math.max(maxNum,index);
}
}
显然,我们还可以使用动态规划的方法来进行解决,首先看两种特殊情况,第一种是数组长度为0,那么直接返回0,第二种是数组长度是1,那么直接返回第一个值即可。然后开始一般情况的讨论,我们把第一个元素记为a,第一个元素和第二个元素的最大值记为b,然后从第三个元素开始遍历,把b值记录,然后计算a与当前下标的值的和与b的最大值赋值给b,然后把原来的b值赋值给a,最终返回b的值,所以根据这个思路就可以写出代码,下面是Python代码部分:
#喷火龙与水箭龟
class Solution:
def rob(self, nums: List[int]) -> int:
lenNums = len(nums)
if nums is None:
return 0
if lenNums == 1:
return nums[0]
a = nums[0]
b = max(nums[0], nums[1])
for jr in range(2,lenNums):
t = b
b = max(a+nums[jr],b)
a = t
return b
从结果来说java版本的递归方法和python版本的动态规划速度都非常不错,应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。