题目
思路
record:错误思路!
当数组数量大于2时,只考虑了数组第0,2,4…位置的总和与第1,3,5位置的总和比较。但是,没考虑到如果某几个不相邻的数的和都比这两个和大呢?所以该方法是不可行的。
正确思路:动态规划和滑动数组(减少空间复杂度)
动态规划基本思想:
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。[来源:百度百科]
说明:
- 用Si记录前i间房间可以偷到的最大金额,Hi记录第i间房间的金额数。
- 当只有1间屋时,可以偷,当有2间时,可以选择数额较大的头。
- 当有3间屋时,可以选择偷与不偷:偷是指可以选择偷第3间房与它不相邻的第一间房(S0+H2);不偷指的是不偷第3间房,只偷第2间房,然后取最大金额(S1)。所以,得出有3间房时可以偷的最大金额。
- 当有4间房时,也可以选择偷与不偷:偷时,则不能偷相邻的第3间房,只能偷第4间房和第2间房的金额总和(S1+H3);不偷时,则是前3间房可以偷到的最大金额(S2)。所以,得出有4间房时可以偷的最大金额。
- 当有n间房时,Sn = max(Sn-1,Sn-2+Hn)(n>=2)
算法实现
class Solution {
public int rob(int[] nums) {
if(nums == null||nums.length == 0){
return 0;
}
int len = nums.length;
if(len == 1){
return nums[0];
}
//记录最大金额的数组
int[] retrast = new int[len];
retrast[0] = nums[0];
retrast[1] = Math.max(nums[0],nums[1]);
for(int i= 2;i<len;i++){
retrast[i] = Math.max(retrast[i-1],retrast[i-2] + nums[i]);
}
return retrast[len-1];
}
}
复杂度分析:
时间复杂度:O(n),n为数组长度。
空间复杂度:O(1),使用了滚动数组,只需存储前两间最高金额,不需要存储整个数组的结果。