Stickler the thief wants to loot money from a societyhaving n houses in a single line. He is a weird person and follows a certain rule when looting the houses. According to the rule, he will never loot two consecutive houses. At the same time, he wants to maximize the amount he loots. The thief knows which house has what amount of money but is unable to come up with an optimal looting strategy. He asks for your help to find the maximum money he can get if he strictly follows the rule. ith house has arr[i] amount of money present in it.
Examples:
Input: arr[] = [6, 5, 5, 7, 4] Output: 15 Explanation: Maximum amount he can get by looting 1st, 3rd and 5th house. Which is 6+5+4=15.
Input: arr[] = [1, 5, 3] Output: 5 Explanation: Loot only 2nd house and get maximum amount of 5.
Input: arr[] = [4, 4, 4, 4] Output: 8 Explanation: The optimal choice is to loot every alternate house. Looting the 1st and 3rd houses, or the 2nd and 4th, both give a maximum total of 4 + 4 = 8.
[Naive Approach] Using Recursion- O(2^n) Time and O(n) Space
The idea is to explore all the possibilities for each house using Recursion. We can start from the last house and for each house, we have two choices:
Rob the current house and skip the house just before it.
Skip the current house and move to the next house.
So, the recurrence relation will be:
maxLootRec(n) = max(arr[n - 1] + maxLootRec(n - 2), maxLootRec(n - 1)), where maxLootRec(n) returns the maximum amount of money which can be stolen if n houses are left.
C++
#include<bits/stdc++.h>usingnamespacestd;// Calculate the maximum stolen value recursivelyintmaxLootRec(vector<int>&arr,intn){// If no houses are left, return 0.if(n<=0)return0;// If only 1 house is left, rob it. if(n==1)returnarr[0];// Two Choices: Rob the nth house and do not rob the nth house intpick=arr[n-1]+maxLootRec(arr,n-2);intnotPick=maxLootRec(arr,n-1);// Return the max of two choicesreturnmax(pick,notPick);}// Function to calculate the maximum stolen valueintfindMaxSum(vector<int>&arr){intn=arr.size();// Call the recursive function for n housesreturnmaxLootRec(arr,n);}intmain(){vector<int>arr={6,5,5,7,4};cout<<findMaxSum(arr);return0;}
Java
classGfG{// Calculate the maximum stolen value recursivelystaticintmaxLootRec(int[]arr,intn){// If no houses are left, return 0.if(n<=0)return0;// If only 1 house is left, rob it. if(n==1)returnarr[0];// Two Choices: Rob the nth house and do not rob the nth house intpick=arr[n-1]+maxLootRec(arr,n-2);intnotPick=maxLootRec(arr,n-1);// Return the max of two choicesreturnMath.max(pick,notPick);}// Function to calculate the maximum stolen valuestaticintfindMaxSum(int[]arr){intn=arr.length;// Call the recursive function for n housesreturnmaxLootRec(arr,n);}publicstaticvoidmain(String[]args){int[]arr={6,5,5,7,4};System.out.println(findMaxSum(arr));}}
Python
defmaxLootRec(arr,n):# If no houses are left, return 0.ifn<=0:return0# If only 1 house is left, rob it. ifn==1:returnarr[0]# Two Choices: Rob the nth house and do not rob the nth house pick=arr[n-1]+maxLootRec(arr,n-2)notPick=maxLootRec(arr,n-1)# Return the max of two choicesreturnmax(pick,notPick)# Function to calculate the maximum stolen valuedeffindMaxSum(arr):n=len(arr)# Call the recursive function for n housesreturnmaxLootRec(arr,n)if__name__=="__main__":arr=[6,5,5,7,4]print(findMaxSum(arr))
C#
usingSystem;classGfG{// Calculate the maximum stolen value recursivelystaticintmaxLootRec(int[]arr,intn){// If no houses are left, return 0.if(n<=0)return0;// If only 1 house is left, rob it. if(n==1)returnarr[0];// Two Choices: Rob the nth house and do not rob the nth house intpick=arr[n-1]+maxLootRec(arr,n-2);intnotPick=maxLootRec(arr,n-1);// Return the max of two choicesreturnMath.Max(pick,notPick);}// Function to calculate the maximum stolen valuestaticintfindMaxSum(int[]arr){intn=arr.Length;// Call the recursive function for n housesreturnmaxLootRec(arr,n);}staticvoidMain(){int[]arr={6,5,5,7,4};Console.WriteLine(findMaxSum(arr));}}
JavaScript
functionmaxLootRec(arr,n){// If no houses are left, return 0.if(n<=0)return0;// If only 1 house is left, rob it. if(n===1)returnarr[0];// Two Choices: Rob the nth house and do not rob the nth house letpick=arr[n-1]+maxLootRec(arr,n-2);letnotPick=maxLootRec(arr,n-1);// Return the max of two choicesreturnMath.max(pick,notPick);}// Function to calculate the maximum stolen valuefunctionfindMaxSum(arr){letn=arr.length;// Call the recursive function for n housesreturnmaxLootRec(arr,n);}letarr=[6,5,5,7,4];console.log(findMaxSum(arr));
Output
15
[Better Approach 1] Using Memoization - O(n) Time and O(n) Space
We can optimize this solution using a memo array of size (n + 1), such that memo[i] represents the maximum value that can be collected from first i houses. Please note that there is only one parameter that changes in recursion and the range of this parameter is from 0 to n.
C++
#include<bits/stdc++.h>usingnamespacestd;intmaxLootRec(constvector<int>&arr,intn,vector<int>&memo){if(n<=0)return0;if(n==1)returnarr[0];// Check if the result is already computedif(memo[n]!=-1)returnmemo[n];intpick=arr[n-1]+maxLootRec(arr,n-2,memo);intnotPick=maxLootRec(arr,n-1,memo);// Store the max of two choices in the memo array and return itmemo[n]=max(pick,notPick);returnmemo[n];}intfindMaxSum(vector<int>&arr){intn=arr.size();// Initialize memo array with -1vector<int>memo(n+1,-1);returnmaxLootRec(arr,n,memo);}intmain(){vector<int>arr={6,5,5,7,4};cout<<findMaxSum(arr);return0;}
Java
importjava.util.Arrays;classGfG{staticintmaxLootRec(int[]arr,intn,int[]memo){if(n<=0)return0;if(n==1)returnarr[0];// Check if the result is already computedif(memo[n]!=-1)returnmemo[n];intpick=arr[n-1]+maxLootRec(arr,n-2,memo);intnotPick=maxLootRec(arr,n-1,memo);// Store the max of two choices in the memo array and return itmemo[n]=Math.max(pick,notPick);returnmemo[n];}// Function to calculate the maximum stolen valuestaticintfindMaxSum(int[]arr){intn=arr.length;// Initialize memo array with -1int[]memo=newint[n+1];Arrays.fill(memo,-1);returnmaxLootRec(arr,n,memo);}publicstaticvoidmain(String[]args){int[]arr={6,5,5,7,4};System.out.println(findMaxSum(arr));}}
Python
defmaxLootRec(arr,n,memo):ifn<=0:return0ifn==1:returnarr[0]# Check if the result is already computedifmemo[n]!=-1:returnmemo[n]pick=arr[n-1]+maxLootRec(arr,n-2,memo)notPick=maxLootRec(arr,n-1,memo)# Store the max of two choices in the memo array and return itmemo[n]=max(pick,notPick)returnmemo[n]deffindMaxSum(arr):n=len(arr)# Initialize memo array with -1memo=[-1]*(n+1)returnmaxLootRec(arr,n,memo)if__name__=="__main__":arr=[6,5,5,7,4]print(findMaxSum(arr))
C#
// C# Program to solve House Robber Problem using// MemoizationusingSystem;classGfG{staticintMaxLootRec(int[]arr,intn,int[]memo){if(n<=0)return0;if(n==1)returnarr[0];// Check if the result is already computedif(memo[n]!=-1)returnmemo[n];intpick=arr[n-1]+MaxLootRec(arr,n-2,memo);intnotPick=MaxLootRec(arr,n-1,memo);// Store the max of two choices in the memo array// and return itmemo[n]=Math.Max(pick,notPick);returnmemo[n];}staticintfindMaxSum(int[]arr){// Initialize memo array with -1intn=arr.Length;int[]memo=newint[n+1];for(inti=0;i<=n;++i){memo[i]=-1;}intresult=MaxLootRec(arr,n,memo);returnresult;}staticvoidMain(){int[]arr={6,5,5,7,4};Console.WriteLine(findMaxSum(arr));}}
JavaScript
// JavaScript Program to solve House Robber Problem using MemoizationfunctionmaxLootRec(arr,n,memo){if(n<=0)return0;if(n===1)returnarr[0];// Check if the result is already computedif(memo[n]!==-1)returnmemo[n];constpick=arr[n-1]+maxLootRec(arr,n-2,memo);constnotPick=maxLootRec(arr,n-1,memo);// Store the max of two choices in the memo array and return itmemo[n]=Math.max(pick,notPick);returnmemo[n];}// Function to calculate the maximum stolen valuefunctionfindMaxSum(arr){constn=arr.length;// Initialize memo array with -1constmemo=newArray(n+1).fill(-1);returnmaxLootRec(arr,n,memo);}constarr=[6,5,5,7,4];console.log(findMaxSum(arr));
Output
15
[Better Approach 2] Using Tabulation - O(n) Time and O(n) Space
The idea is to build the solution in bottom-up manner. We create a dp[] array of size n+1 where dp[i] represents the maximum value that can be collected with first i houses. We first fill the known values, dp[0] and dp[1] and then fill the remaining values using the formula: dp[i] = max(arr[i] + dp[i - 2], dp[i - 1]). The final result will be stored at dp[n].
C++
#include<bits/stdc++.h>usingnamespacestd;// Function to calculate the maximum stolen value using bottom-up DPintfindMaxSum(vector<int>&arr){intn=arr.size();// Create a dp array to store the maximum loot at each housevector<int>dp(n+1,0);// Base casesdp[0]=0;dp[1]=arr[0];// Fill the dp array using the bottom-up approachfor(inti=2;i<=n;i++)dp[i]=max(arr[i-1]+dp[i-2],dp[i-1]);returndp[n];}intmain(){vector<int>arr={6,5,5,7,4};cout<<findMaxSum(arr)<<endl;return0;}
Java
classGfG{// Function to calculate the maximum stolen value using bottom-up DPstaticintfindMaxSum(int[]arr){intn=arr.length;// Create a dp array to store the maximum loot at each houseint[]dp=newint[n+1];// Base casesdp[0]=0;dp[1]=arr[0];// Fill the dp array using the bottom-up approachfor(inti=2;i<=n;i++){dp[i]=Math.max(arr[i-1]+dp[i-2],dp[i-1]);}returndp[n];}publicstaticvoidmain(String[]args){int[]arr={6,5,5,7,4};System.out.println(findMaxSum(arr));}}
Python
deffindMaxSum(arr):n=len(arr)# Create a dp array to store the maximum loot at each housedp=[0]*(n+1)# Base casesdp[0]=0dp[1]=arr[0]# Fill the dp array using the bottom-up approachforiinrange(2,n+1):dp[i]=max(arr[i-1]+dp[i-2],dp[i-1])returndp[n]arr=[6,5,5,7,4]print(findMaxSum(arr))
C#
usingSystem;classGfG{// Function to calculate the maximum stolen value using bottom-up DPstaticintfindMaxSum(int[]arr){intn=arr.Length;// Create a dp array to store the maximum loot at each houseint[]dp=newint[n+1];// Base casesdp[0]=0;dp[1]=arr[0];// Fill the dp array using the bottom-up approachfor(inti=2;i<=n;i++){dp[i]=Math.Max(arr[i-1]+dp[i-2],dp[i-1]);}returndp[n];}staticvoidMain(){int[]arr={6,5,5,7,4};Console.WriteLine(findMaxSum(arr));}}
JavaScript
functionfindMaxSum(arr){constn=arr.length;// Create a dp array to store the maximum loot at each houseconstdp=newArray(n+1).fill(0);// Base casesdp[0]=0;dp[1]=arr[0];// Fill the dp array using the bottom-up approachfor(leti=2;i<=n;i++)dp[i]=Math.max(arr[i-1]+dp[i-2],dp[i-1]);returndp[n];}constarr=[6,5,5,7,4];console.log(findMaxSum(arr));
Output
15
[Expected Approach ] Using Space-Optimized DP - O(n) Time and O(1) Space
On observing the dp[] array in the previous approach, it can be seen that the answer at the current index depends only on the last two values. In other words, dp[i] depends only on dp[i - 1] and dp[i - 2]. So, instead of storing the result in an array, we can simply use two variables to store the last and second last result.
C++
#include<bits/stdc++.h>usingnamespacestd;// Function to calculate the maximum stolen valueintfindMaxSum(vector<int>&arr){intn=arr.size();if(n==0)return0;if(n==1)returnarr[0];// Set previous 2 valuesintsecondLast=0,last=arr[0];// Compute current value using previous two values// The final current value would be our resultintres;for(inti=1;i<n;i++){res=max(arr[i]+secondLast,last);secondLast=last;last=res;}returnres;}intmain(){vector<int>arr={6,5,5,7,4};cout<<findMaxSum(arr)<<endl;return0;}
Java
importjava.util.Arrays;classGfG{// Function to calculate the maximum stolen valuestaticintfindMaxSum(int[]arr){intn=arr.length;if(n==0)return0;if(n==1)returnarr[0];// Set previous 2 valuesintsecondLast=0,last=arr[0];// Compute current value using previous// two values. The final current value// would be our resultintres=0;for(inti=1;i<n;i++){res=Math.max(arr[i]+secondLast,last);secondLast=last;last=res;}returnres;}publicstaticvoidmain(String[]args){int[]arr={6,5,5,7,4};System.out.println(findMaxSum(arr));}}
Python
deffindMaxSum(arr):n=len(arr)ifn==0:return0ifn==1:returnarr[0]# Set previous 2 valuessecondLast=0last=arr[0]# Compute current value using previous two values# The final current value would be our resultres=0foriinrange(1,n):res=max(arr[i]+secondLast,last)secondLast=lastlast=resreturnresarr=[6,5,5,7,4]print(findMaxSum(arr))
C#
usingSystem;classGfG{// Function to calculate the maximum stolen valuestaticintfindMaxSum(int[]arr){intn=arr.Length;if(n==0)return0;if(n==1)returnarr[0];// Set previous 2 valuesintsecondLast=0,last=arr[0];// Compute current value using previous two values// The final current value would be our resultintres=0;for(inti=1;i<n;i++){res=Math.Max(arr[i]+secondLast,last);secondLast=last;last=res;}returnres;}staticvoidMain(){int[]arr={6,5,5,7,4};Console.WriteLine(findMaxSum(arr));}}
JavaScript
functionfindMaxSum(arr){constn=arr.length;if(n===0)return0;if(n===1)returnarr[0];// Set previous 2 valuesletsecondLast=0,last=arr[0];// Compute current value using previous two values// The final current value would be our resultletres;for(leti=1;i<n;i++){res=Math.max(arr[i]+secondLast,last);secondLast=last;last=res;}returnres;}constarr=[6,5,5,7,4];console.log(findMaxSum(arr));