Given an array arr[] of positive integers, find the maximum possible sum of a subsequence such that no three selected elements are consecutive in the original array.
Examples :Â
Input: arr[] = [1, 2, 3]
Output: 5
Explanation: We can't take three of them, so answer is 2 + 3 = 5.Input: arr[] = [3000, 2000, 1000, 3, 10]
Output: 5013
Explanation: 3000 + 2000 + 3 + 10 = 5013.
Table of Content
[Naive Approach] Recursion by Trying All Valid Picks - O(3 ^ n) Time and O(n) Space
At each index, we make one of three choices -
- Skip It
- Pick only Current
- Pick it along with the previous element.
Each choice ensures no three consecutive elements are ever selected. We return the maximum across all three choices.
#include <iostream>
#include <vector>
using namespace std;
// Helper function to recursively compute max sum with three choices
int solve(vector<int>& arr, int n) {
// Base cases: empty array, single element, two elements
if (n <= 0) return 0;
if (n == 1) return arr[0];
if (n == 2) return arr[0] + arr[1];
// Skip the current element
int notPick = solve(arr, n - 1);
// Pick only the current element
int pickOne = arr[n - 1] + solve(arr, n - 2);
// Pick both current and previous element
int pickTwo = arr[n - 1] + arr[n - 2] + solve(arr, n - 3);
// Return the maximum of all three choices
return max({notPick, pickOne, pickTwo});
}
int findMaxSum(vector<int>& arr) {
// Start recursion with full array size
return solve(arr, arr.size());
}
int main() {
vector<int> arr = {1, 2, 3};
cout << findMaxSum(arr);
return 0;
}
class Solution {
// Helper function to recursively compute max sum with three choices
private static int solve(int[] arr, int n) {
// Base cases: empty array, single element, two elements
if (n <= 0) return 0;
if (n == 1) return arr[0];
if (n == 2) return arr[0] + arr[1];
// Skip the current element
int notPick = solve(arr, n - 1);
// Pick only the current element
int pickOne = arr[n - 1] + solve(arr, n - 2);
// Pick both current and previous element
int pickTwo = arr[n - 1] + arr[n - 2] + solve(arr, n - 3);
// Return the maximum of all three choices
return Math.max(notPick, Math.max(pickOne, pickTwo));
}
static int findMaxSum(int[] arr) {
// Start recursion with full array size
return solve(arr, arr.length);
}
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(findMaxSum(arr));
}
}
# Helper function to recursively compute max sum with three choices
def solve(arr, n):
# Base cases: empty array, single element, two elements
if n <= 0:
return 0
if n == 1:
return arr[0]
if n == 2:
return arr[0] + arr[1]
# Skip the current element
notPick = solve(arr, n - 1)
# Pick only the current element
pickOne = arr[n - 1] + solve(arr, n - 2)
# Pick both current and previous element
pickTwo = arr[n - 1] + arr[n - 2] + solve(arr, n - 3)
# Return the maximum of all three choices
return max(notPick, pickOne, pickTwo)
def findMaxSum(arr):
# Start recursion with full array size
return solve(arr, len(arr))
arr = [1, 2, 3]
print(findMaxSum(arr))
using System;
class Solution {
// Helper function to recursively compute max sum with three choices
private static int Solve(int[] arr, int n) {
// Base cases: empty array, single element, two elements
if (n <= 0) return 0;
if (n == 1) return arr[0];
if (n == 2) return arr[0] + arr[1];
// Skip the current element
int notPick = Solve(arr, n - 1);
// Pick only the current element
int pickOne = arr[n - 1] + Solve(arr, n - 2);
// Pick both current and previous element
int pickTwo = arr[n - 1] + arr[n - 2] + Solve(arr, n - 3);
// Return the maximum of all three choices
return Math.Max(notPick, Math.Max(pickOne, pickTwo));
}
static int findMaxSum(int[] arr) {
// Start recursion with full array size
return Solve(arr, arr.Length);
}
static void Main() {
int[] arr = {1, 2, 3};
Console.WriteLine(findMaxSum(arr));
}
}
// Helper function to recursively compute max sum with three choices
function solve(arr, n) {
// Base cases: empty array, single element, two elements
if (n <= 0) return 0;
if (n === 1) return arr[0];
if (n === 2) return arr[0] + arr[1];
// Skip the current element
const notPick = solve(arr, n - 1);
// Pick only the current element
const pickOne = arr[n - 1] + solve(arr, n - 2);
// Pick both current and previous element
const pickTwo = arr[n - 1] + arr[n - 2] + solve(arr, n - 3);
// Return the maximum of all three choices
return Math.max(notPick, pickOne, pickTwo);
}
function findMaxSum(arr) {
// Start recursion with full array size
return solve(arr, arr.length);
}
// Driver Code
const arr = [1, 2, 3];
console.log(findMaxSum(arr));
Output
5
[Expected Approach] Using Dynamic Programming - O(n) Time and O(1) Space
Since the same subproblems repeat across branches, the time complexity grows exponentially. Therefore we use Dynamic programming to solve this problem.
At each element, we have three choices: skip it, take it while skipping the previous element, or take it along with the previous element while skipping the one before them. The maximum sum at each position is the best of these choices. Since only the last three states are needed, the solution can be optimized to use constant extra space.
Step :
- Handle arrays of size 1 and 2 separately.
- Initialize the answers for the first three positions.
- For each remaining element, consider: skipping it, taking it and skipping the previous element and taking it along with the previous element.
- Store only the last three DP states.
#include <iostream>
#include <vector>
using namespace std;
int findMaxSum(vector<int>& arr) {
int n = arr.size();
if (n == 1) return arr[0];
if (n == 2) return arr[0] + arr[1];
int dp0 = arr[0];
int dp1 = arr[0] + arr[1];
int dp2 = max(dp1, max(arr[0] + arr[2], arr[1] + arr[2]));
// Process remaining elements.
for (int i = 3; i < n; i++) {
int curr = max(dp2, max(dp1 + arr[i], dp0 + arr[i - 1] + arr[i]));
dp0 = dp1;
dp1 = dp2;
dp2 = curr;
}
return dp2;
}
int main() {
vector<int> arr = {1, 2, 3};
cout << findMaxSum(arr);
return 0;
}
class GFG {
static int findMaxSum(int[] arr) {
int n = arr.length;
if (n == 1) return arr[0];
if (n == 2) return arr[0] + arr[1];
int dp0 = arr[0];
int dp1 = arr[0] + arr[1];
int dp2 = Math.max(dp1, Math.max(arr[0] + arr[2], arr[1] + arr[2]));
// Process remaining elements.
for (int i = 3; i < n; i++) {
int curr = Math.max(dp2, Math.max(dp1 + arr[i], dp0 + arr[i - 1] + arr[i]));
dp0 = dp1;
dp1 = dp2;
dp2 = curr;
}
return dp2;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(findMaxSum(arr));
}
}
def findMaxSum(arr):
n = len(arr)
if n == 1:
return arr[0]
if n == 2:
return arr[0] + arr[1]
dp0 = arr[0]
dp1 = arr[0] + arr[1]
dp2 = max(dp1, arr[0] + arr[2], arr[1] + arr[2])
# Process remaining elements.
for i in range(3, n):
curr = max(dp2, dp1 + arr[i], dp0 + arr[i - 1] + arr[i])
dp0 = dp1
dp1 = dp2
dp2 = curr
return dp2
arr = [1, 2, 3]
print(findMaxSum(arr))
using System;
class GFG
{
static int FindMaxSum(int[] arr)
{
int n = arr.Length;
if (n == 1) return arr[0];
if (n == 2) return arr[0] + arr[1];
int dp0 = arr[0];
int dp1 = arr[0] + arr[1];
int dp2 = Math.Max(dp1, Math.Max(arr[0] + arr[2], arr[1] + arr[2]));
// Process remaining elements.
for (int i = 3; i < n; i++)
{
int curr = Math.Max(dp2, Math.Max(dp1 + arr[i], dp0 + arr[i - 1] + arr[i]));
dp0 = dp1;
dp1 = dp2;
dp2 = curr;
}
return dp2;
}
static void Main()
{
int[] arr = { 1, 2, 3 };
Console.WriteLine(FindMaxSum(arr));
}
}
function findMaxSum(arr) {
const n = arr.length;
if (n === 1) return arr[0];
if (n === 2) return arr[0] + arr[1];
let dp0 = arr[0];
let dp1 = arr[0] + arr[1];
let dp2 = Math.max(dp1, arr[0] + arr[2], arr[1] + arr[2]);
// Process remaining elements.
for (let i = 3; i < n; i++) {
const curr = Math.max(dp2, dp1 + arr[i], dp0 + arr[i - 1] + arr[i]);
dp0 = dp1;
dp1 = dp2;
dp2 = curr;
}
return dp2;
}
// Driver Code
const arr = [1, 2, 3];
console.log(findMaxSum(arr));
Output
5