该题来自leetcode,原题如下:
You 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.
这是一道DP问题,首先该题符合“最优子结构”,该题的递推公式:dp(n) = max(dp(n-1), dp(n-2) + nums[n]),另外根据“重叠子问题”原则,如果仅仅使用简单的递归求解,则会有严重的重复计算,时间复杂度成指数增长,所以要额外开销一个数组来存储已经计算出来的dp(i)值。
方法一、递归法
public int dpRob(int[] nums, int n, int[] array) { if (n < 0) return 0;if(array[n] == -1) array[n] = Math.max(dpRob(nums, n-1, array), dpRob(nums, n-2, array) + nums[n]); return array[n]; } public int rob(int[] nums) { int[] array = new int[nums.length]; Arrays.fill(array, -1); //此处数组元素要初始化为负数 return dpRob(nums, nums.length-1, array); }
方法二:迭代法
public int rob(int[] nums) { if(nums.length == 0) return 0; 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]; }
进阶:
若这些房子成环形排列,即第一个房子和最后一个房子相邻,求此时和的最大值。
分析:可以把原数组nums分成两个子数组,转化为线性排列求解,一个数组nums1下标是从0到n-2,另一个数组nums2下标是从1到n-1,两个子数组求解结果中较大的结果为该题的解。
Java递归代码如下:
int dpRob(int[] nums, int n, int[] array) { if (n < 0) return 0; if(array[n] == -1) array[n] = Math.max(dpRob(nums, n-1, array), dpRob(nums, n-2, array) + nums[n]); return array[n]; } public int rob(int[] nums) { if (nums.length == 0) return 0; if (nums.length == 1) return nums[0]; int[] nums1 = new int[nums.length-1]; int[] nums2 = new int[nums.length-1]; System.arraycopy(nums, 0, nums1, 0, nums.length-1); System.arraycopy(nums, 1, nums2, 0, nums.length-1); int[] array = new int[nums.length]; Arrays.fill(array, -1); int result1 = dpRob(nums1, nums1.length-1, array); Arrays.fill(array, -1); int result2 = dpRob(nums2, nums2.length-1, array); return Math.max(result1, result2); }
时间: 2024-10-23 16:35:45