package com.freetymekiyan.algorithms.level.easy; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * 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. * <p> * 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. * <p> * Company Tags: LinkedIn, Airbnb * Tags: Dynamic Programming * Similar Problems: (M) Maximum Product Subarray, (M) House Robber II, (M) Paint House, (E) Paint Fence, (M) House * Robber III */ public class HouseRobber { private HouseRobber hr; /** * DP. Space Optimized. * Max amount of house n is either rob the previous house or rob this house. * Recurrence relation: * max[n] = max(max[n - 2] + nums[n], max[n - 1]) * Optimization: * Use constant variables instead of an array. */ public int rob(int[] nums) { if (nums == null || nums.length == 0) { return 0; } if (nums.length == 1) { return nums[0]; } int preMax = nums[0]; int max = Math.max(nums[0], nums[1]); for (int i = 2; i < nums.length; i++) { int temp = preMax; preMax = max; max = Math.max(temp + nums[i], preMax); } return max; } /** * DP. More compact code. */ public int robB(int[] nums) { int preMax = 0; int max = 0; for (int i = 0; i < nums.length; i++) { int curMax = Math.max(preMax + nums[i], max); preMax = max; max = curMax; } return max; } @Before public void setUp() { hr = new HouseRobber(); } @Test public void testInvalidInput() { Assert.assertEquals(0, hr.rob(null)); } @Test public void testEdgeCases() { int[] input = {}; Assert.assertEquals(0, hr.rob(input)); input = new int[]{1}; Assert.assertEquals(1, hr.rob(input)); // 10 -> 10 input = new int[]{10}; Assert.assertEquals(10, hr.rob(input)); // 1, 2 -> 2 input = new int[]{1, 2}; Assert.assertEquals(2, hr.rob(input)); // 2, 1 -> 2 input = new int[]{2, 1}; Assert.assertEquals(2, hr.rob(input)); } @Test public void testWithExamples() { // 1, 2, 3 -> 4 int[] input = {1, 2, 3}; Assert.assertEquals(4, hr.rob(input)); // 1, 2, 3, 4 -> 6 input = new int[]{1, 2, 3, 4}; Assert.assertEquals(6, hr.rob(input)); // 2, 8, 3, 6, 5 -> 14 input = new int[]{2, 8, 3, 6, 5}; Assert.assertEquals(14, hr.rob(input)); } @After public void tearDown() { hr = null; } }