-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHouseRobber.java
More file actions
152 lines (122 loc) · 4.98 KB
/
HouseRobber.java
File metadata and controls
152 lines (122 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package Algorithms.DynamicProgramming;
/**
* <pre>
* [2,7,9,3,1] -> Max of [2,0,9,0,1] and [0,7,0,3,0]
* or can we skip more that 1 house?
* [2,1,1,2] -- it's 4
* so, two cases -> skip 1 or skip 2 that's how we can cover all big houses
* no need to skip 3 or 4 houses as we include them in skip 1, skip 2 scenario
* top down memo dp ---> Math.max(n-2, n-3) and base case? i < 0 => 0
* save in dp
* Note that we can also skip the 1st house
* </pre>
* @author Srinivas Vadige, srinivas.vadige@gmail.com
* @since 29 Oct 2024
*/
public class HouseRobber {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 1};
System.out.println("robBottomUpNoMemory: " + robBottomUpNoMemory(nums));
System.out.println("robBottomUpTabulation: " + robBottomUpTabulation(nums));
System.out.println("robTopDownMemo: " + robTopDownMemo(nums));
}
public static int robBottomUpNoMemory(int[] nums) {
int rob1=0, rob2=0; // dummy houses
// [rob1, rob2, nums[i], nums[i+1], nums[i+2] ......]
for(int i=0; i<nums.length; i++) {
// [rob1, rob2, temp]
int temp = Math.max(rob1 + nums[i], rob2); // till now how much money we can rob
rob1 = rob2;
rob2 = temp;
}
return rob2;
}
/**
* <pre>
*
* 0 0 1 2 3 1
* |___|___|___|___|___|___|
* p c n
* p c n
* p c n
*
* consider that we have two dummy houses before we start robbing
* Note that we are just making decisions here based on "is rob 3rd house" condition & store the max robbed money in nth house even if we do npt rob there
* Like, what if we rob 3rd house (n+p) and what if we rob 2nd house (c). And we keep the max robbed money in 3rd house
* p is the previous max money we can rob if we choose 3rd house instead of 2nd house
* If "is rob 3rd house" failed? i.e n+p < c 2nd house then we can change our decision to rob 2nd house and it predecessors
* i.e temp = max money we can rob until this point - with our decision making tree
*
* Finally we store max money in c "nums.length - 1" house but can not say that p is second max
* In for loop we go to next house then the previous 'c' house will become 'p' 3rd house for the new next house and 'c' as 2nd house
* that is the reason why we assign c value to p and temp value to c
*
* </pre>
* @see https://youtu.be/73r3KWiEvyk?si=3RWYu64W2GSjlXtq
*/
public static int robBottomUpNoMemory2(int[] nums) {
int prev = 0;
int curr = 0; // dummy houses money
for (int n : nums) {
// ➕©️🔵 -> ©️🔵
int next = Math.max(prev + n, curr); // "is rob 3rd house?" + max we can rob until this point
prev = curr;
curr = next;
}
return curr;
}
/**
* <pre>
* same as above
*
* 1 2 3 1
* |___|___|___|___|
* p c n
*
* rob "n and p" or only rob "c" -- but here curr = next; Note that temp is different and nums[i] i.e n is different
* </pre>
*/
public static int robBottomUpTabulation(int[] nums) {
if (nums.length == 1) return nums[0];
int[] dp = new int[nums.length];
dp[0] = nums[0];
dp[1] = Math.max(dp[0], nums[1]);
for (int i = 2; i < nums.length; i++){
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]); // next = Math.max(prev + n, curr);
}
return dp[nums.length - 1];
}
/**
[2, 7, 9, 3, 1]
*/
public static int robBottomUpTabulation2(int[] nums) {
int n=nums.length;
if(n==1) return nums[0];
else if(n==2) return Math.max(nums[0], nums[1]);
// [9, 3, 1][0] -- [0] is robbed[n] which is dummy house in robbed array -> robbed[robbed.length-1]
int[] dp = new int[n+1];
dp[n-1]=nums[n-1];
dp[n-2]=nums[n-2];
for(int i=n-3; i>=0; i--) {
dp[i] = nums[i] + Math.max(dp[i+2], dp[i+3]);
}
return Math.max(dp[0], dp[1]);
}
/**
* Unlike Bottom Up approach, here we don't store max money in nth house
* instead we only go to the eligible houses
*/
public static int robTopDownMemo(int[] nums) {
Integer[] dp = new Integer[nums.length]; // we use int[] instead of Integer[] because we can have [0,0,0,0] as input or initialize int[] and loop & set -1
int max = rec(0, nums, dp);
if(nums.length > 1) max = Math.max(rec(1, nums, dp), max);
return max; // or Math.max(dp[0], dp[1]);
}
private static int rec(int i, int[] nums, Integer[] dp) {
if(i >= nums.length) return 0;
if (dp[i] != null) return dp[i];
dp[i] = nums[i] + Math.max(rec(i+2, nums, dp), rec(i+3, nums, dp));
System.out.println(dp[i] + " <= (" + ((i+2)>=nums.length?0:dp[i+2]) + " or " + ((i+3)>=nums.length?0:dp[i+3]) + ") + " + nums[i]);
return dp[i];
}
}