package com.thealgorithms.dynamicprogramming;
/**
* Class to find the maximum sum of non-adjacent elements in an array. This
* class contains two approaches: one with O(n) space complexity and another
* with O(1) space optimization. For more information, refer to
* https://takeuforward.org/data-structure/maximum-sum-of-non-adjacent-elements-dp-5/
*/
final class MaximumSumOfNonAdjacentElements {
private MaximumSumOfNonAdjacentElements() {
}
/**
* Approach 1: Uses a dynamic programming array to store the maximum sum at
* each index. Time Complexity: O(n) - where n is the length of the input
* array. Space Complexity: O(n) - due to the additional dp array.
* @param arr The input array of integers.
* @return The maximum sum of non-adjacent elements.
*/
public static int getMaxSumApproach1(int[] arr) {
if (arr.length == 0) {
return 0; // Check for empty array
}
int n = arr.length;
int[] dp = new int[n];
// Base case: Maximum sum if only one element is present.
dp[0] = arr[0];
for (int ind = 1; ind < n; ind++) {
// Case 1: Do not take the current element, carry forward the previous max
// sum.
int notTake = dp[ind - 1];
// Case 2: Take the current element, add it to the max sum up to two
// indices before.
int take = arr[ind];
if (ind > 1) {
take += dp[ind - 2];
}
// Store the maximum of both choices in the dp array.
dp[ind] = Math.max(take, notTake);
}
return dp[n - 1];
}
/**
* Approach 2: Optimized space complexity approach using two variables instead
* of an array. Time Complexity: O(n) - where n is the length of the input
* array. Space Complexity: O(1) - as it only uses constant space for two
* variables.
* @param arr The input array of integers.
* @return The maximum sum of non-adjacent elements.
*/
public static int getMaxSumApproach2(int[] arr) {
if (arr.length == 0) {
return 0; // Check for empty array
}
int n = arr.length;
// Two variables to keep track of previous two results:
// prev1 = max sum up to the last element (n-1)
// prev2 = max sum up to the element before last (n-2)
int prev1 = arr[0]; // Base case: Maximum sum for the first element.
int prev2 = 0;
for (int ind = 1; ind < n; ind++) {
// Case 1: Do not take the current element, keep the last max sum.
int notTake = prev1;
// Case 2: Take the current element and add it to the result from two
// steps back.
int take = arr[ind];
if (ind > 1) {
take += prev2;
}
// Calculate the current maximum sum and update previous values.
int current = Math.max(take, notTake);
// Shift prev1 and prev2 for the next iteration.
prev2 = prev1;
prev1 = current;
}
return prev1;
}
}