Given an array arr[] where each element shows the amount of money in a row of houses built in a line. A robber wants to steal money, but cannot rob two houses adjacent to each other because it will set off an alarm.
Find the maximum money the robber can steal without robbing two adjacent houses.
Examples:
Input: arr[] = [6, 7, 1, 3, 8, 2, 4]
Output: 19
Explanation: The thief will steal from house 1, 3, 5 and 7, total money = 6 + 1 + 8 + 4 = 19.
Input: arr[] = [5, 3, 4, 11, 2]
Output: 16
Explanation: Thief will steal from house 1 and 4, total money = 5 + 11 = 16.
Table of Content
[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.

//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
// Calculate the maximum stolen value recursively
int findMaxSumRec(vector<int> &arr, int n) {
// If no houses are left, return 0.
if (n <= 0) return 0;
// If only 1 house is left, rob it.
if (n == 1) return arr[0];
// Two Choices: Rob the nth house and do not rob the nth house
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2);
int notPick = findMaxSumRec(arr, n - 1);
// Return the max of two choices
return max(pick, notPick);
}
// Function to calculate the maximum stolen value
int findMaxSum(vector<int>&arr) {
int n = arr.size();
// Call the recursive function for n houses
return findMaxSumRec(arr, n);
}
//Driver Code Starts
int main() {
vector<int> arr = {6, 7, 1, 3, 8, 2, 4};
cout << findMaxSum(arr);
return 0;
}
//Driver Code Ends
//Driver Code Starts
#include <stdio.h>
//Driver Code Ends
// Calculate the maximum stolen value recursively
int findMaxSumRec(int arr[], int n) {
// If no houses are left, return 0.
if (n <= 0) return 0;
// If only 1 house is left, rob it.
if (n == 1) return arr[0];
// Two Choices: Rob the nth house and do not rob the nth house
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2);
int notPick = findMaxSumRec(arr, n - 1);
// Return the max of two choices
return (pick > notPick) ? pick : notPick;
}
// Function to calculate the maximum stolen value
int findMaxSum(int arr[], int n) {
// Call the recursive function for n houses
return findMaxSumRec(arr, n);
}
//Driver Code Starts
int main() {
int arr[] = {6, 7, 1, 3, 8, 2, 4};
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d", findMaxSum(arr, n));
return 0;
}
//Driver Code Ends
//Driver Code Starts
class GFG {
//Driver Code Ends
// Calculate the maximum stolen value recursively
static int findMaxSumRec(int[] arr, int n) {
// If no houses are left, return 0.
if (n <= 0) return 0;
// If only 1 house is left, rob it.
if (n == 1) return arr[0];
// Two Choices: Rob the nth house and do not rob the nth house
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2);
int notPick = findMaxSumRec(arr, n - 1);
// Return the max of two choices
return Math.max(pick, notPick);
}
// Function to calculate the maximum stolen value
static int findMaxSum(int[] arr) {
int n = arr.length;
// Call the recursive function for n houses
return findMaxSumRec(arr, n);
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
System.out.println(findMaxSum(arr));
}
}
//Driver Code Ends
# Calculate the maximum stolen value recursively
def findMaxSumRec(arr, n):
# If no houses are left, return 0.
if n <= 0:
return 0
# If only 1 house is left, rob it.
if n == 1:
return arr[0]
# Two Choices: Rob the nth house and do not rob the nth house
pick = arr[n - 1] + findMaxSumRec(arr, n - 2)
notPick = findMaxSumRec(arr, n - 1)
# Return the max of two choices
return max(pick, notPick)
# Function to calculate the maximum stolen value
def findMaxSum(arr):
n = len(arr)
# Call the recursive function for n houses
return findMaxSumRec(arr, n)
if __name__ == "__main__":
#Driver Code Starts
arr = [6, 7, 1, 3, 8, 2, 4]
print(findMaxSum(arr))
#Driver Code Ends
//Driver Code Starts
using System;
class GFG {
//Driver Code Ends
// Calculate the maximum stolen value recursively
static int findMaxSumRec(int[] arr, int n) {
// If no houses are left, return 0.
if (n <= 0) return 0;
// If only 1 house is left, rob it.
if (n == 1) return arr[0];
// Two Choices: Rob the nth house and do not rob the nth house
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2);
int notPick = findMaxSumRec(arr, n - 1);
// Return the max of two choices
return Math.Max(pick, notPick);
}
// Function to calculate the maximum stolen value
static int findMaxSum(int[] arr) {
int n = arr.Length;
// Call the recursive function for n houses
return findMaxSumRec(arr, n);
}
//Driver Code Starts
static void Main() {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
Console.WriteLine(findMaxSum(arr));
}
}
//Driver Code Ends
// Calculate the maximum stolen value recursively
function findMaxSumRec(arr, n) {
// If no houses are left, return 0.
if (n <= 0) return 0;
// If only 1 house is left, rob it.
if (n === 1) return arr[0];
// Two Choices: Rob the nth house and do not rob the nth house
let pick = arr[n - 1] + findMaxSumRec(arr, n - 2);
let notPick = findMaxSumRec(arr, n - 1);
// Return the max of two choices
return Math.max(pick, notPick);
}
// Function to calculate the maximum stolen value
function findMaxSum(arr) {
let n = arr.length;
// Call the recursive function for n houses
return findMaxSumRec(arr, n);
}
let arr = [6, 7, 1, 3, 8, 2, 4];
//Driver Code Starts
console.log(findMaxSum(arr));
//Driver Code Ends
Output
19
[Better Approach] Using Memoization - O(n) Time and O(n) Space
In the recursive approach, many subproblems are solved multiple times because the same states are revisited again and again - this leads to overlapping subproblems and increases the time complexity.
We can optimize the recursive solution by using a memoization array of size (n + 1). Here, memo[i] represents the maximum amount of money that can be stolen from the first i houses.
In the recursive approach, only one parameter - the number of houses changes during each recursive call. Since the range of this parameter is from 0 to n, we can store and reuse previously computed results for each state to avoid redundant calculations.
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
int findMaxSumRec( vector<int>& arr, int n, vector<int>& memo) {
if (n <= 0) return 0;
if (n == 1) return arr[0];
// Check if the result is already computed
if (memo[n] != -1) return memo[n];
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2, memo);
int notPick = findMaxSumRec(arr, n - 1, memo);
// Store the max of two choices in the memo array and return it
memo[n] = max(pick, notPick);
return memo[n];
}
int findMaxSum(vector<int>& arr) {
int n = arr.size();
// Initialize memo array with -1
vector<int> memo(n + 1, -1);
return findMaxSumRec(arr, n, memo);
}
//Driver Code Starts
int main() {
vector<int>arr = {6, 7, 1, 3, 8, 2, 4};
cout << findMaxSum(arr);
return 0;
}
//Driver Code Ends
//Driver Code Starts
#include <stdio.h>
//Driver Code Ends
// Calculate the maximum stolen value recursively with memoization
int findMaxSumRec(int arr[], int n, int memo[]) {
if (n <= 0) return 0;
if (n == 1) return arr[0];
// Check if the result is already computed
if (memo[n] != -1) return memo[n];
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2, memo);
int notPick = findMaxSumRec(arr, n - 1, memo);
// Store the max of two choices in the memo array and return it
memo[n] = (pick > notPick) ? pick : notPick;
return memo[n];
}
int findMaxSum(int arr[], int n) {
// Initialize memo array with -1
int memo[n + 1];
for (int i = 0; i <= n; i++) memo[i] = -1;
return findMaxSumRec(arr, n, memo);
}
//Driver Code Starts
int main() {
int arr[] = {6, 7, 1, 3, 8, 2, 4};
int n = sizeof(arr)/sizeof(arr[0]);
printf("%d", findMaxSum(arr, n));
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.Arrays;
class GFG {
//Driver Code Ends
static int findMaxSumRec(int[] arr, int n, int[] memo) {
if (n <= 0) return 0;
if (n == 1) return arr[0];
// Check if the result is already computed
if (memo[n] != -1) return memo[n];
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2, memo);
int notPick = findMaxSumRec(arr, n - 1, memo);
// Store the max of two choices in the memo array and return it
memo[n] = Math.max(pick, notPick);
return memo[n];
}
static int findMaxSum(int[] arr) {
int n = arr.length;
// Initialize memo array with -1
int[] memo = new int[n + 1];
Arrays.fill(memo, -1);
return findMaxSumRec(arr, n, memo);
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
System.out.println(findMaxSum(arr));
}
}
//Driver Code Ends
# Calculate the maximum stolen value recursively with memoization
def findMaxSumRec(arr, n, memo):
if n <= 0:
return 0
if n == 1:
return arr[0]
# Check if the result is already computed
if memo[n] != -1:
return memo[n]
pick = arr[n - 1] + findMaxSumRec(arr, n - 2, memo)
notPick = findMaxSumRec(arr, n - 1, memo)
# Store the max of two choices in the memo array and return it
memo[n] = max(pick, notPick)
return memo[n]
# Function to calculate the maximum stolen value
def findMaxSum(arr):
n = len(arr)
# Initialize memo array with -1
memo = [-1] * (n + 1)
return findMaxSumRec(arr, n, memo)
#Driver Code Starts
if __name__ == "__main__":
arr = [6, 7, 1, 3, 8, 2, 4]
print(findMaxSum(arr))
#Driver Code Ends
//Driver Code Starts
using System;
class GFG {
//Driver Code Ends
static int findMaxSumRec(int[] arr, int n, int[] memo) {
if (n <= 0) return 0;
if (n == 1) return arr[0];
// Check if the result is already computed
if (memo[n] != -1) return memo[n];
int pick = arr[n - 1] + findMaxSumRec(arr, n - 2, memo);
int notPick = findMaxSumRec(arr, n - 1, memo);
// Store the max of two choices in the memo array and return it
memo[n] = Math.Max(pick, notPick);
return memo[n];
}
static int findMaxSum(int[] arr) {
int n = arr.Length;
// Initialize memo array with -1
int[] memo = new int[n + 1];
for (int i = 0; i <= n; i++) memo[i] = -1;
return findMaxSumRec(arr, n, memo);
}
//Driver Code Starts
static void Main() {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
Console.WriteLine(findMaxSum(arr));
}
}
//Driver Code Ends
function findMaxSumRec(arr, n, memo) {
if (n <= 0) return 0;
if (n === 1) return arr[0];
// Check if the result is already computed
if (memo[n] !== -1) return memo[n];
let pick = arr[n - 1] + findMaxSumRec(arr, n - 2, memo);
let notPick = findMaxSumRec(arr, n - 1, memo);
// Store the max of two choices in the memo array and return it
memo[n] = Math.max(pick, notPick);
return memo[n];
}
function findMaxSum(arr) {
let n = arr.length;
// Initialize memo array with -1
let memo = new Array(n + 1).fill(-1);
return findMaxSumRec(arr, n, memo);
}
//Driver Code
//Driver Code Starts
let arr = [6, 7, 1, 3, 8, 2, 4];
console.log(findMaxSum(arr));
//Driver Code Ends
Output
19
[Expected Approach 1] Using Tabulation - O(n) Time and O(n) Space
In this approach, we build the solution iteratively from the ground up, starting with the smallest subproblems. We first define the base cases, and then gradually compute the answers for larger problems using the results of previously solved smaller ones.
Here, we create a dp[] array where dp[i] represents the maximum amount of money that can be stolen from the first i houses.
Initially,
- we set dp[0] = 0 because if there are no houses, no money can be stolen.
- we set dp[1] = arr[0] because if there is only one house, the thief will steal from that house.
Then, we iterate through the remaining houses and fill the dp[] array using this formula:
- if the thief decides to rob the current house (i), then they must skip the previous house (i−1) in that case- arr[i] + dp[i−2].
- If the thief skips the current house, then the total will simply be the maximum money till the previous house → dp[i−1].
- so the answer will be the maximum of both dp[i]=max(arr[i]+dp[i−2], dp[i−1])
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
int findMaxSum(vector<int>& arr) {
int n = arr.size();
// Create a dp array to store the maximum loot at each house
vector<int> dp(n+1, 0);
// Base cases
dp[0] = 0;
dp[1] = arr[0];
// Fill the dp array using the bottom-up approach
for (int i = 2; i <= n; i++)
dp[i] = max(arr[i - 1] + dp[i - 2], dp[i - 1]);
return dp[n];
}
//Driver Code Starts
int main() {
vector<int>arr = {6, 7, 1, 3, 8, 2, 4};
cout << findMaxSum(arr) << endl;
return 0;
}
//Driver Code Ends
//Driver Code Starts
#include <stdio.h>
//Driver Code Ends
// Function to calculate the maximum stolen value
int findMaxSum(int arr[], int n) {
// Create a dp array to store the maximum loot at each house
int dp[n + 1];
// Base cases
dp[0] = 0;
dp[1] = arr[0];
// Fill the dp array using the bottom-up approach
for (int i = 2; i <= n; i++)
dp[i] = (arr[i - 1] + dp[i - 2] > dp[i - 1]) ?
(arr[i - 1] + dp[i - 2]) : dp[i - 1];
return dp[n];
}
//Driver Code Starts
int main() {
int arr[] = {6, 7, 1, 3, 8, 2, 4};
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d
", findMaxSum(arr, n));
return 0;
}
//Driver Code Ends
//Driver Code Starts
class GFG {
//Driver Code Ends
static int findMaxSum(int[] arr) {
int n = arr.length;
// Create a dp array to store the maximum loot at each house
int[] dp = new int[n + 1];
// Base cases
dp[0] = 0;
dp[1] = arr[0];
// Fill the dp array using the bottom-up approach
for (int i = 2; i <= n; i++)
dp[i] = Math.max(arr[i - 1] + dp[i - 2], dp[i - 1]);
return dp[n];
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
System.out.println(findMaxSum(arr));
}
}
//Driver Code Ends
def findMaxSum(arr):
n = len(arr)
# Create a dp array to store the maximum loot at each house
dp = [0] * (n + 1)
# Base cases
dp[0] = 0
dp[1] = arr[0]
# Fill the dp array using the bottom-up approach
for i in range(2, n + 1):
dp[i] = max(arr[i - 1] + dp[i - 2], dp[i - 1])
return dp[n]
if __name__ == "__main__":
#Driver Code Starts
arr = [6, 7, 1, 3, 8, 2, 4]
print(findMaxSum(arr))
#Driver Code Ends
//Driver Code Starts
using System;
//Driver Code Ends
class GFG {
static int findMaxSum(int[] arr) {
int n = arr.Length;
// Create a dp array to store the maximum loot at each house
int[] dp = new int[n + 1];
// Base cases
dp[0] = 0;
dp[1] = arr[0];
// Fill the dp array using the bottom-up approach
for (int i = 2; i <= n; i++)
dp[i] = Math.Max(arr[i - 1] + dp[i - 2], dp[i - 1]);
return dp[n];
}
//Driver Code Starts
static void Main() {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
Console.WriteLine(findMaxSum(arr));
}
}
//Driver Code Ends
function findMaxSum(arr) {
let n = arr.length;
// Create a dp array to store the maximum loot at each house
let dp = new Array(n + 1).fill(0);
// Base cases
dp[0] = 0;
dp[1] = arr[0];
// Fill the dp array using the bottom-up approach
for (let i = 2; i <= n; i++)
dp[i] = Math.max(arr[i - 1] + dp[i - 2], dp[i - 1]);
return dp[n];
}
//Driver Code
//Driver Code Starts
let arr = [6, 7, 1, 3, 8, 2, 4];
console.log(findMaxSum(arr));
//Driver Code Ends
Output
19
[Expected Approach 2] 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.
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
int findMaxSum(vector<int> &arr) {
int n = arr.size();
if (n == 0)
return 0;
if (n == 1)
return arr[0];
// Set previous 2 values
int secondLast = 0, last = arr[0];
// Compute current value using previous two values
// The final current value would be our result
int res;
for (int i = 1; i < n; i++) {
res = max(arr[i] + secondLast, last);
secondLast = last;
last = res;
}
return res;
}
//Driver Code Starts
int main() {
vector<int> arr = {6, 7, 1, 3, 8, 2, 4};
cout << findMaxSum(arr) << endl;
return 0;
}
//Driver Code Ends
//Driver Code Starts
#include <stdio.h>
//Driver Code Ends
int findMaxSum(int arr[], int n) {
if (n == 0)
return 0;
if (n == 1)
return arr[0];
// Set previous 2 values
int secondLast = 0, last = arr[0];
// Compute current value using previous two values
// The final current value would be our result
int res;
for (int i = 1; i < n; i++) {
res = (arr[i] + secondLast > last) ? (arr[i] + secondLast) : last;
secondLast = last;
last = res;
}
return res;
}
//Driver Code Starts
int main() {
int arr[] = {6, 7, 1, 3, 8, 2, 4};
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d
", findMaxSum(arr, n));
return 0;
}
//Driver Code Ends
//Driver Code Starts
class GFG {
//Driver Code Ends
static int findMaxSum(int[] arr) {
int n = arr.length;
if (n == 0)
return 0;
if (n == 1)
return arr[0];
// Set previous 2 values
int secondLast = 0, last = arr[0];
// Compute current value using previous two values
// The final current value would be our result
int res = 0;
for (int i = 1; i < n; i++) {
res = Math.max(arr[i] + secondLast, last);
secondLast = last;
last = res;
}
return res;
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
System.out.println(findMaxSum(arr));
}
}
//Driver Code Ends
def findMaxSum(arr):
n = len(arr)
if n == 0:
return 0
if n == 1:
return arr[0]
# Set previous 2 values
secondLast, last = 0, arr[0]
# Compute current value using previous two values
# The final current value would be our result
for i in range(1, n):
res = max(arr[i] + secondLast, last)
secondLast = last
last = res
return res
if __name__ == "__main__":
#Driver Code Starts
arr = [6, 7, 1, 3, 8, 2, 4]
print(findMaxSum(arr))
#Driver Code Ends
//Driver Code Starts
using System;
class GFG {
//Driver Code Ends
static int findMaxSum(int[] arr) {
int n = arr.Length;
if (n == 0)
return 0;
if (n == 1)
return arr[0];
// Set previous 2 values
int secondLast = 0, last = arr[0];
// Compute current value using previous two values
// The final current value would be our result
int res = 0;
for (int i = 1; i < n; i++) {
res = Math.Max(arr[i] + secondLast, last);
secondLast = last;
last = res;
}
return res;
}
//Driver Code Starts
static void Main() {
int[] arr = {6, 7, 1, 3, 8, 2, 4};
Console.WriteLine(findMaxSum(arr));
}
}
//Driver Code Ends
function findMaxSum(arr) {
let n = arr.length;
if (n === 0)
return 0;
if (n === 1)
return arr[0];
// Set previous 2 values
let secondLast = 0, last = arr[0];
// Compute current value using previous two values
// The final current value would be our result
let res;
for (let i = 1; i < n; i++) {
res = Math.max(arr[i] + secondLast, last);
secondLast = last;
last = res;
}
return res;
}
//Driver Code
//Driver Code Starts
let arr = [6, 7, 1, 3, 8, 2, 4];
console.log(findMaxSum(arr));
//Driver Code Ends
Output
19