Given an array of positive numbers, find the maximum sum of a subsequence such that no two numbers in the subsequence should be adjacent in the array.
Examples:
Input: arr[] = {5, 5, 10, 100, 10, 5} Output: 110 Explanation: Pick the subsequence {5, 100, 5}. The sum is 110 and no two elements are adjacent. This is the highest possible sum.
Input: arr[] = {3, 2, 7, 10} Output: 13 Explanation: The subsequence is {3, 10}. This gives the highest possible sum = 13.
Input: arr[] = {3, 2, 5, 10, 7} Output: 15 Explanation: Pick the subsequence {3, 5, 7}. The sum is 15.
[Naive Approach] Using Recursion- O(2^n) Time and O(n) Space
The idea is to explore all the possibilities for each element using Recursion. We can start from the last element and for each element, we have two choices:
Pick the current element and skip the element just before it.
Skip the current element and move to the element just before it.
So, the recurrence relation will be:
maxSumRec(n) = max(arr[n - 1] + maxSumRec(n - 2), maxSumRec(n - 1)), where maxSumRec(n) returns the maximum sum if n elements are left.
Output
19
Time Complexity: O(2n). Every element has 2 choices to pick and not pick. Auxiliary Space: O(n).For recursion stack space
[Better Approach] 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 elements. Please note that there is only one parameter that changes in recursion and the range of this parameter is from 0 to n.
Output
19
Time Complexity: O(n). Every element is computed only once. Auxiliary Space: O(n).For recursion stack space and memo array.
[Expected Approach 1] 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 sum that can be obtained with first i elements. 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].
Output
19
Time Complexity: O(n), Every element is computed only once. Auxiliary Space O(n), We are using a dp array of size n.
[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.
Output
19
Time Complexity: O(n), Every value is computed only once. Auxiliary Space: O(1), as we are using only two variables.