Maximum sum in circular array such that no two elements are adjacent (original) (raw)

Given an array **arr[] which represents houses arranged in a circle, where each house has a certain value. A thief aims to maximize the total stolen value without robbing two adjacent houses. Since the houses are in a circle, the first and last houses are also considered adjacent. Determine the **maximum amount the thief can steal.

**Examples:

**Input: arr[] = [2, 2, 3, 1, 2]
**Output: 5
**Explanation: Maximum stolen value: arr[0] + arr[2] = 2 + 3 = 5 orarr[2] + arr[4] = 3 + 2 = 5.

**Input: arr[] = [2, 3, 2]
**Output: 3
**Explanation: arr[0] and arr[2] can't be robbed simultaneously because they are adjacent houses.

Table of Content

[Naive Approach] Using Recursion - O(2^n) Time and O(n) Space

The idea is to solve this problem by handling the circular constraint, where the first and last houses are adjacent.

To avoid robbing both of them together, we divide the problem into two linear cases:

For each case, the thief has two choices at every house:

We solve both cases separately using recursion and then take the maximum of the two results.

C++ `

//Driver Code Starts #include #include using namespace std; //Driver Code Ends

// Calculate the maximum stolen value recursively int maxValRec(vector &arr, int i, int j) {

// If no houses are left, return 0.
if (i> j)  return 0;

  // If only 1 house is left, rob it. 
if (i == j)  return arr[i];

// Two Choices: 
// Rob the jth house and skip the (j-1)th house 
int pick = arr[j] + maxValRec(arr, i, j-2);

// Skip the jth house
int notPick = maxValRec(arr, i, j-1);

// Return the max of two choices
return max(pick, notPick);

}

// Function to calculate the maximum stolen value int maxValue(vector& arr) { int n = arr.size();

int ans = 0;

// Skip the last house
ans = max(ans, maxValRec(arr, 0, n-2));

// Skip the first house 
ans = max(ans, maxValRec(arr, 1, n-1));

return ans;

}

//Driver Code Starts int main() { vector arr = {2, 2, 3, 1, 2}; cout << maxValue(arr); return 0; }

//Driver Code Ends

Java

//Driver Code Starts class GfG { //Driver Code Ends

// Calculate the maximum stolen value recursively
static int maxValRec(int[] arr, int i, int j) {
    
    // If no houses are left, return 0.
    if (i > j) return 0;

    // If only 1 house is left, rob it. 
    if (i == j) return arr[i];

    // Two Choices: 
    // Rob the jth house and skip the (j-1)th house 
    int pick = arr[j] + maxValRec(arr, i, j - 2);
    
    // Skip the jth house
    int notPick = maxValRec(arr, i, j - 1);

    // Return the max of two choices
    return Math.max(pick, notPick);
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.length;

    int ans = 0;
    
    // Skip the last house
    ans = Math.max(ans, maxValRec(arr, 0, n - 2));
    
    // Skip the first house 
    ans = Math.max(ans, maxValRec(arr, 1, n - 1));
    
    return ans;
}

//Driver Code Starts public static void main(String[] args) { int[] arr = {2, 2, 3, 1, 2}; System.out.println(maxValue(arr)); } }

//Driver Code Ends

Python

Calculate the maximum stolen value recursively

def maxValRec(arr, i, j):

# If no houses are left, return 0.
if i > j:
    return 0

# If only 1 house is left, rob it. 
if i == j:
    return arr[i]

# Two Choices: 
# Rob the jth house and skip the (j-1)th house 
pick = arr[j] + maxValRec(arr, i, j - 2)

# Skip the jth house
notPick = maxValRec(arr, i, j - 1)

# Return the max of two choices
return max(pick, notPick)

Function to calculate the maximum stolen value

def maxValue(arr): n = len(arr)

ans = 0

# Skip the last house
ans = max(ans, maxValRec(arr, 0, n - 2))

# Skip the first house 
ans = max(ans, maxValRec(arr, 1, n - 1))

return ans

if name == "main": #Driver Code Starts arr = [2, 2, 3, 1, 2] print(maxValue(arr))

#Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

// Calculate the maximum stolen value recursively
static int maxValRec(int[] arr, int i, int j) {
    
    // If no houses are left, return 0.
    if (i > j) return 0;

    // If only 1 house is left, rob it. 
    if (i == j) return arr[i];

    // Two Choices: 
    // Rob the jth house and skip the (j-1)th house 
    int pick = arr[j] + maxValRec(arr, i, j - 2);
    
    // Skip the jth house
    int notPick = maxValRec(arr, i, j - 1);

    // Return the max of two choices
    return Math.Max(pick, notPick);
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.Length;

    int ans = 0;
    
    // Skip the last house
    ans = Math.Max(ans, maxValRec(arr, 0, n - 2));
    
    // Skip the first house 
    ans = Math.Max(ans, maxValRec(arr, 1, n - 1));
    
    return ans;
}

//Driver Code Starts static void Main() { int[] arr = {2, 2, 3, 1, 2}; Console.WriteLine(maxValue(arr)); } }

//Driver Code Ends

JavaScript

// Calculate the maximum stolen value recursively function maxValRec(arr, i, j) {

// If no houses are left, return 0.
if (i > j) return 0;

// If only 1 house is left, rob it. 
if (i == j) return arr[i];

// Two Choices: 
// Rob the jth house and skip the (j-1)th house 
let pick = arr[j] + maxValRec(arr, i, j - 2);

// Skip the jth house
let notPick = maxValRec(arr, i, j - 1);

// Return the max of two choices
return Math.max(pick, notPick);

}

// Function to calculate the maximum stolen value function maxValue(arr) { let n = arr.length;

let ans = 0;

// Skip the last house
ans = Math.max(ans, maxValRec(arr, 0, n - 2));

// Skip the first house 
ans = Math.max(ans, maxValRec(arr, 1, n - 1));

return ans;

}

//Drievr Code //Driver Code Starts let arr = [2, 2, 3, 1, 2]; console.log(maxValue(arr));

//Driver Code Ends

`

[Better Approach - 1 ] Using Top-Down DP (Memoization) - O(n) Time and O(n) Space

In the recursive solution, there are many overlapping subproblems because the same states are solved multiple times.
To avoid this repetition, we can use memoization where we store the results of already computed subproblems in a separate array (memo). Before solving any subproblem, we first check in the memo[i] if it has been computed earlier. If yes, we simply reuse the stored result instead of recalculating it.

C++ `

//Driver Code Starts #include #include using namespace std; //Driver Code Ends

// Calculate the maximum stolen value recursively int maxValRec(vector &arr, int i, int j, vector &memo) {

// If no houses are left, return 0.
if (i> j)  return 0;

  // If only 1 house is left, rob it. 
if (i == j)  return arr[i];

// If value is memoized
if (memo[j] != -1) return memo[j];

// Two Choices: 
// Rob the jth house and skip the (j-1)th house 
int pick = arr[j] + maxValRec(arr, i, j-2, memo);

// Skip the jth house
int notPick = maxValRec(arr, i, j-1, memo);

// Return the max of two choices
return memo[j] = max(pick, notPick);

}

// Function to calculate the maximum stolen value int maxValue(vector& arr) { int n = arr.size();

int ans = 0;

vector<int> memo(n, -1);

// Skip the last house
ans = max(ans, maxValRec(arr, 0, n-2, memo));

// Reset the memo array
for (int i=0; i<n; i++) memo[i] = -1;

// Skip the first house 
ans = max(ans, maxValRec(arr, 1, n-1, memo));

return ans;

}

//Driver Code Starts int main() { vector arr = {2, 2, 3, 1, 2}; cout << maxValue(arr); return 0; }

//Driver Code Ends

Java

//Driver Code Starts import java.util.Arrays;

class GfG { //Driver Code Ends

// Calculate the maximum stolen value recursively
static int maxValRec(int[] arr, int i, int j, int[] memo) {
    
    // If no houses are left, return 0.
    if (i > j) return 0;

    // If only 1 house is left, rob it. 
    if (i == j) return arr[i];

    // If value is memoized
    if (memo[j] != -1) return memo[j];

    // Two Choices: 
    // Rob the jth house and skip the (j-1)th house 
    int pick = arr[j] + maxValRec(arr, i, j - 2, memo);
    
    // Skip the jth house
    int notPick = maxValRec(arr, i, j - 1, memo);

    // Return the max of two choices
    return memo[j] = Math.max(pick, notPick);
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.length;

    int ans = 0;
    
    int[] memo = new int[n];
    Arrays.fill(memo, -1);
    
    // Skip the last house
    ans = Math.max(ans, maxValRec(arr, 0, n - 2, memo));
    
    // Reset the memo array
    Arrays.fill(memo, -1);
    
    // Skip the first house 
    ans = Math.max(ans, maxValRec(arr, 1, n - 1, memo));
    
    return ans;
}

//Driver Code Starts public static void main(String[] args) { int[] arr = {2, 2, 3, 1, 2}; System.out.println(maxValue(arr)); } }

//Driver Code Ends

Python

Calculate the maximum stolen value recursively

def maxValRec(arr, i, j, memo):

# If no houses are left, return 0.
if i > j:
    return 0

# If only 1 house is left, rob it. 
if i == j:
    return arr[i]

# If value is memoized
if memo[j] != -1:
    return memo[j]

# Two Choices: 
# Rob the jth house and skip the (j-1)th house 
pick = arr[j] + maxValRec(arr, i, j - 2, memo)

# Skip the jth house
notPick = maxValRec(arr, i, j - 1, memo)

# Return the max of two choices
memo[j] = max(pick, notPick)
return memo[j]

Function to calculate the maximum stolen value

def maxValue(arr): n = len(arr)

ans = 0

memo = [-1] * n

# Skip the last house
ans = max(ans, maxValRec(arr, 0, n - 2, memo))

# Reset the memo array
memo = [-1] * n

# Skip the first house 
ans = max(ans, maxValRec(arr, 1, n - 1, memo))

return ans

if name == "main": #Driver Code Starts arr = [2, 2, 3, 1, 2] print(maxValue(arr))

#Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

// Calculate the maximum stolen value recursively
static int maxValRec(int[] arr, int i, int j, int[] memo) {
    
    // If no houses are left, return 0.
    if (i > j) return 0;

    // If only 1 house is left, rob it. 
    if (i == j) return arr[i];

    // If value is memoized
    if (memo[j] != -1) return memo[j];

    // Two Choices: 
    // Rob the jth house and skip the (j-1)th house 
    int pick = arr[j] + maxValRec(arr, i, j - 2, memo);
    
    // Skip the jth house
    int notPick = maxValRec(arr, i, j - 1, memo);

    // Return the max of two choices
    return memo[j] = Math.Max(pick, notPick);
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.Length;

    int ans = 0;
    
    int[] memo = new int[n];
    Array.Fill(memo, -1);
    
    // Skip the last house
    ans = Math.Max(ans, maxValRec(arr, 0, n - 2, memo));
    
    // Reset the memo array
    Array.Fill(memo, -1);
    
    // Skip the first house 
    ans = Math.Max(ans, maxValRec(arr, 1, n - 1, memo));
    
    return ans;
}

//Driver Code Starts static void Main() { int[] arr = {2, 2, 3, 1, 2}; Console.WriteLine(maxValue(arr)); } }

//Driver Code Ends

JavaScript

// Calculate the maximum stolen value recursively function maxValRec(arr, i, j, memo) {

// If no houses are left, return 0.
if (i > j) return 0;

// If only 1 house is left, rob it. 
if (i == j) return arr[i];

// If value is memoized
if (memo[j] !== -1) return memo[j];

// Two Choices: 
// Rob the jth house and skip the (j-1)th house 
let pick = arr[j] + maxValRec(arr, i, j - 2, memo);

// Skip the jth house
let notPick = maxValRec(arr, i, j - 1, memo);

// Return the max of two choices
memo[j] = Math.max(pick, notPick);
return memo[j];

}

// Function to calculate the maximum stolen value function maxValue(arr) { let n = arr.length;

let ans = 0;

let memo = new Array(n).fill(-1);

// Skip the last house
ans = Math.max(ans, maxValRec(arr, 0, n - 2, memo));

// Reset the memo array
memo.fill(-1);

// Skip the first house 
ans = Math.max(ans, maxValRec(arr, 1, n - 1, memo));

return ans;

}

//Driver Code //Driver Code Starts let arr = [2, 2, 3, 1, 2]; console.log(maxValue(arr));

//Driver Code Ends

`

[Better Approach - 2] Using Bottom-Up DP (Tabulation) - O(n) Time and O(n) Space

The main idea is to build the solution iteratively using a DP table where each entry represents the maximum money that can be stolen up to that house.

The relation that helps us compute this is: dp[j] = max(arr[j] + dp[j-2], dp[j-1])
This ensures we always choose the option that gives the maximum total amount without robbing two adjacent houses.

The formula dp[j] = max(arr[j] + dp[j−2], dp[j−1]) comes from two choices:

We take the maximum of these two options to ensure the thief always gets the highest possible amount.

C++ `

//Driver Code Starts #include #include using namespace std; //Driver Code Ends

// Tabulation approach to find the maximum // value. int maxValTab(int x, int y, vector &arr) { int n = arr.size(); if (n == 2) return max(arr[0], arr[1]); vector dp(n);

// For first house, taking is only option
dp[x] = arr[x];

// For second house, we can either take
// from 1st or 2nd.
dp[x+1] = max(arr[x], arr[x+1]);

for (int j=x+2; j<=y; j++) {
    int take = arr[j] + dp[j-2];
    int noTake = dp[j-1];
    
    dp[j] = max(take, noTake);
}

return dp[y];

}

// Function to calculate the maximum stolen value int maxValue(vector& arr) { int n = arr.size();

// Base cases
if (n == 0) return 0;
if (n == 1) return arr[0];

int ans = 0;

// Skipping last house 
ans = max(ans, maxValTab(0, n-2, arr));

// Skipping first house 
ans = max(ans, maxValTab(1, n-1, arr));

return ans;

}

//Driver Code Starts int main() { vector arr = {2, 2, 3, 1, 2}; cout << maxValue(arr); return 0; }

//Driver Code Ends

Java

//Driver Code Starts import java.util.Arrays;

class GfG { //Driver Code Ends

// Tabulation approach to find the maximum 
// value.
static int maxValTab(int x, int y, int[] arr) {
    int n = arr.length;
    if (n == 2) return Math.max(arr[0], arr[1]);
    int[] dp = new int[n];
    
    // For first house, taking is only option
    dp[x] = arr[x];
    
    // For second house, we can either take
    // from 1st or 2nd.
    dp[x+1] = Math.max(arr[x], arr[x+1]);
    
    for (int j = x + 2; j <= y; j++) {
        int take = arr[j] + dp[j - 2];
        int noTake = dp[j - 1];
        
        dp[j] = Math.max(take, noTake);
    }
    
    return dp[y];
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.length;
    
    // Base cases
    if (n == 0) return 0;
    if (n == 1) return arr[0];

    int ans = 0;
    
    // Skipping last house 
    ans = Math.max(ans, maxValTab(0, n - 2, arr));
    
    // Skipping first house 
    ans = Math.max(ans, maxValTab(1, n - 1, arr));
    
    return ans;
}

//Driver Code Starts public static void main(String[] args) { int[] arr = {2, 2, 3, 1, 2}; System.out.println(maxValue(arr)); } }

//Driver Code Ends

Python

Tabulation approach to find the maximum

value.

def maxValTab(x, y, arr): n = len(arr) if n == 2: return max(arr[0], arr[1]) dp = [0] * n

# For first house, taking is only option
dp[x] = arr[x]

# For second house, we can either take
# from 1st or 2nd.
dp[x+1] = max(arr[x], arr[x+1])

for j in range(x + 2, y + 1):
    take = arr[j] + dp[j - 2]
    noTake = dp[j - 1]
    
    dp[j] = max(take, noTake)

return dp[y]

Function to calculate the maximum stolen value

def maxValue(arr): n = len(arr)

# Base cases
if n == 0:
    return 0
if n == 1:
    return arr[0]

ans = 0

# Skipping last house 
ans = max(ans, maxValTab(0, n - 2, arr))

# Skipping first house 
ans = max(ans, maxValTab(1, n - 1, arr))

return ans

if name == "main": #Driver Code Starts arr = [2, 2, 3, 1, 2] print(maxValue(arr))

#Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

// Tabulation approach to find the maximum 
// value
static int maxValTab(int x, int y, int[] arr) {
    int n = arr.Length;
    if (n == 2) return Math.Max(arr[0], arr[1]);
    int[] dp = new int[n];
    
    // For first house, taking is only option
    dp[x] = arr[x];
    
    // For second house, we can either take
    // from 1st or 2nd.
    dp[x+1] = Math.Max(arr[x], arr[x+1]);
    
    for (int j = x + 2; j <= y; j++) {
        int take = arr[j] + dp[j - 2];
        int noTake = dp[j - 1];
        
        dp[j] = Math.Max(take, noTake);
    }
    
    return dp[y];
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.Length;
    
    // Base cases
    if (n == 0) return 0;
    if (n == 1) return arr[0];

    int ans = 0;
    
    // Skipping last house 
    ans = Math.Max(ans, maxValTab(0, n - 2, arr));
    
    // Skipping first house 
    ans = Math.Max(ans, maxValTab(1, n - 1, arr));
    
    return ans;
}

//Driver Code Starts static void Main() { int[] arr = {2, 2, 3, 1, 2}; Console.WriteLine(maxValue(arr)); } }

//Driver Code Ends

JavaScript

// Tabulation approach to find the maximum // value. function maxValTab(x, y, arr) { let n = arr.length; if (n === 2) return Math.max(arr[0], arr[1]); let dp = new Array(n).fill(0);

// For first house, taking is only option
dp[x] = arr[x];

// For second house, we can either take
// from 1st or 2nd.
dp[x + 1] = Math.max(arr[x], arr[x + 1]);

for (let j = x + 2; j <= y; j++) {
    let take = arr[j] + dp[j - 2];
    let noTake = dp[j - 1];
    
    dp[j] = Math.max(take, noTake);
}

return dp[y];

}

// Function to calculate the maximum stolen value function maxValue(arr) { let n = arr.length;

// Base cases
if (n === 0) return 0;
if (n === 1) return arr[0];

let ans = 0;

// Skipping last house 
ans = Math.max(ans, maxValTab(0, n - 2, arr));

// Skipping first house 
ans = Math.max(ans, maxValTab(1, n - 1, arr));

return ans;

}

//Driver Code //Driver Code Starts let arr = [2, 2, 3, 1, 2]; console.log(maxValue(arr));

//Driver Code Ends

`

[Expected Approach ] Using Space Optimized DP - O(n) Time and O(1) Space

In the previous approach, we used an array to store results for all states. However, if we look closely, to calculate the result for the current house, we only need the values from the previous two houses.This means there’s no need to store all previous results.
We can simply keep track of the last two computed values and update them as we move forward.

C++ `

//Driver Code Starts #include #include using namespace std; //Driver Code Ends

// Tabulation approach to find the maximum // value. int maxValTab(int x, int y, vector &arr) { int n = arr.size(); if (n == 2) return max(arr[0], arr[1]); // For first house, taking is only option int prev2 = arr[x];

// For second house, we can either take
// from 1st or 2nd.
int prev1 = max(arr[x], arr[x+1]);

for (int j=x+2; j<=y; j++) {
    int take = arr[j] + prev2;
    int noTake = prev1;
    
    int curr = max(take, noTake);
    
    // update states
    prev2 = prev1;
    prev1 = curr;
}

return prev1;

}

// Function to calculate the maximum stolen value int maxValue(vector& arr) { int n = arr.size();

// Base cases
if (n == 0) return 0;
if (n == 1) return arr[0];

int ans = 0;

// Skipping last house 
ans = max(ans, maxValTab(0, n-2, arr));

// Skipping first house 
ans = max(ans, maxValTab(1, n-1, arr));

return ans;

}

//Driver Code Starts int main() { vector arr = {2, 2, 3, 1, 2}; cout << maxValue(arr); return 0; }

//Driver Code Ends

Java

//Driver Code Starts import java.util.Arrays;

class GfG { //Driver Code Ends

// Tabulation approach to find the maximum 
// value.
static int maxValTab(int x, int y, int[] arr) {
    int n = arr.length;
    if (n == 2) return Math.max(arr[0], arr[1]);
    // For first house, taking is only option
    int prev2 = arr[x];
    
    // For second house, we can either take
    // from 1st or 2nd.
    int prev1 = Math.max(arr[x], arr[x + 1]);
    
    for (int j = x + 2; j <= y; j++) {
        int take = arr[j] + prev2;
        int noTake = prev1;
        
        int curr = Math.max(take, noTake);
        
        // update states
        prev2 = prev1;
        prev1 = curr;
    }
    
    return prev1;
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.length;
    
    // Base cases
    if (n == 0) return 0;
    if (n == 1) return arr[0];

    int ans = 0;
    
    // Skipping last house 
    ans = Math.max(ans, maxValTab(0, n - 2, arr));
    
    // Skipping first house 
    ans = Math.max(ans, maxValTab(1, n - 1, arr));
    
    return ans;
}

//Driver Code Starts public static void main(String[] args) { int[] arr = {2, 2, 3, 1, 2}; System.out.println(maxValue(arr)); } }

//Driver Code Ends

Python

Tabulation approach to find the maximum

#value. def maxValTab(x, y, arr): n = len(arr) if n == 2: return max(arr[0], arr[1]) # For first house, taking is only option prev2 = arr[x]

# For second house, we can either take
# from 1st or 2nd.
prev1 = max(arr[x], arr[x + 1])

for j in range(x + 2, y + 1):
    take = arr[j] + prev2
    noTake = prev1
    
    curr = max(take, noTake)
    
    # update states
    prev2 = prev1
    prev1 = curr

return prev1

Function to calculate the maximum stolen value

def maxValue(arr): n = len(arr)

# Base cases
if n == 0:
    return 0
if n == 1:
    return arr[0]

ans = 0

# Skipping last house 
ans = max(ans, maxValTab(0, n - 2, arr))

# Skipping first house 
ans = max(ans, maxValTab(1, n - 1, arr))

return ans

#Driver Code Starts if name == "main": arr = [2, 2, 3, 1, 2] print(maxValue(arr))

#Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

// Tabulation approach to find the maximum 
// value. 
static int maxValTab(int x, int y, int[] arr) {
    int n = arr.Length;
    if (n == 2) return Math.Max(arr[0], arr[1]);
    // For first house, taking is only option
    int prev2 = arr[x];
    
    // For second house, we can either take
    // from 1st or 2nd.
    int prev1 = Math.Max(arr[x], arr[x + 1]);
    
    for (int j = x + 2; j <= y; j++) {
        int take = arr[j] + prev2;
        int noTake = prev1;
        
        int curr = Math.Max(take, noTake);
        
        // update states
        prev2 = prev1;
        prev1 = curr;
    }
    
    return prev1;
}

// Function to calculate the maximum stolen value
static int maxValue(int[] arr) {
    int n = arr.Length;
    
    // Base cases
    if (n == 0) return 0;
    if (n == 1) return arr[0];

    int ans = 0;
    
    // Skipping last house 
    ans = Math.Max(ans, maxValTab(0, n - 2, arr));
    
    // Skipping first house 
    ans = Math.Max(ans, maxValTab(1, n - 1, arr));
    
    return ans;
}

//Driver Code Starts static void Main(string[] args) { int[] arr = {2, 2, 3, 1, 2}; Console.WriteLine(maxValue(arr)); } }

//Driver Code Ends

JavaScript

// Tabulation approach to find the maximum // value. function maxValTab(x, y, arr) { let n = arr.length; if (n === 2) return Math.max(arr[0], arr[1]); // For first house, taking is only option let prev2 = arr[x];

// For second house, we can either take
// from 1st or 2nd.
let prev1 = Math.max(arr[x], arr[x + 1]);

for (let j = x + 2; j <= y; j++) {
    let take = arr[j] + prev2;
    let noTake = prev1;
    
    let curr = Math.max(take, noTake);
    
    // update states
    prev2 = prev1;
    prev1 = curr;
}

return prev1;

}

// Function to calculate the maximum stolen value function maxValue(arr) { let n = arr.length;

// Base cases
if (n === 0) return 0;
if (n === 1) return arr[0];

let ans = 0;

// Skipping last house 
ans = Math.max(ans, maxValTab(0, n - 2, arr));

// Skipping first house 
ans = Math.max(ans, maxValTab(1, n - 1, arr));

return ans;

}

//Driver Code //Driver Code Starts let arr = [2, 2, 3, 1, 2]; console.log(maxValue(arr));

//Driver Code Ends

`