Printing Maximum Sum Increasing Subsequence
Last Updated :
24 Jun, 2022
The Maximum Sum Increasing Subsequence problem is to find the maximum sum subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order.
Examples:
Input: [1, 101, 2, 3, 100, 4, 5]
Output: [1, 2, 3, 100]
Input: [3, 4, 5, 10]
Output: [3, 4, 5, 10]
Input: [10, 5, 4, 3]
Output: [10]
Input: [3, 2, 6, 4, 5, 1]
Output: [3, 4, 5]
In previous post, we have discussed the Maximum Sum Increasing Subsequence problem. However, the post only covered code related to finding maximum sum of increasing subsequence, but not to the construction of subsequence. In this post, we will discuss how to construct Maximum Sum Increasing Subsequence itself.
Let arr[0..n-1] be the input array. We define vector L such that L[i] is itself is a vector that stores Maximum Sum Increasing Subsequence of arr[0..i] that ends with arr[i]. Therefore for index i, L[i] can be recursively written as
L[0] = {arr[0]}
L[i] = {MaxSum(L[j])} + arr[i] where j < i and arr[j] < arr[i]
= arr[i], if there is no j such that arr[j] < arr[i]
For example, for array [3, 2, 6, 4, 5, 1],
L[0]: 3
L[1]: 2
L[2]: 3 6
L[3]: 3 4
L[4]: 3 4 5
L[5]: 1
Below is the implementation of the above idea –
C++
#include <iostream>
#include <vector>
using namespace std;
int findSum(vector< int > arr)
{
int sum = 0;
for ( int i : arr)
sum += i;
return sum;
}
void printMaxSumIS( int arr[], int n)
{
vector<vector< int > > L(n);
L[0].push_back(arr[0]);
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < i; j++) {
if ((arr[i] > arr[j])
&& (findSum(L[i]) < findSum(L[j])))
L[i] = L[j];
}
L[i].push_back(arr[i]);
}
vector< int > res = L[0];
for (vector< int > x : L)
if (findSum(x) > findSum(res))
res = x;
for ( int i : res)
cout << i << " " ;
cout << endl;
}
int main()
{
int arr[] = { 3, 2, 6, 4, 5, 1 };
int n = sizeof (arr) / sizeof (arr[0]);
printMaxSumIS(arr, n);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int findSum(Vector<Integer> arr)
{
int sum = 0 ;
for ( int i : arr)
sum += i;
return sum;
}
static void printMaxSumIs( int [] arr, int n)
{
@SuppressWarnings ( "unchecked" )
Vector<Integer>[] L = new Vector[n];
for ( int i = 0 ; i < n; i++)
L[i] = new Vector<>();
L[ 0 ].add(arr[ 0 ]);
for ( int i = 1 ; i < n; i++) {
for ( int j = 0 ; j < i; j++) {
if ((arr[i] > arr[j])
&& (findSum(L[i]) < findSum(L[j]))) {
for ( int k : L[j])
if (!L[i].contains(k))
L[i].add(k);
}
}
L[i].add(arr[i]);
}
Vector<Integer> res = new Vector<>(L[ 0 ]);
for (Vector<Integer> x : L)
if (findSum(x) > findSum(res))
res = x;
for ( int i : res)
System.out.print(i + " " );
System.out.println();
}
public static void main(String[] args)
{
int [] arr = { 3 , 2 , 6 , 4 , 5 , 1 };
int n = arr.length;
printMaxSumIs(arr, n);
}
}
|
Python3
def findSum(arr):
summ = 0
for i in arr:
summ + = i
return summ
def printMaxSumIS(arr, n):
L = [[] for i in range (n)]
L[ 0 ].append(arr[ 0 ])
for i in range ( 1 , n):
for j in range (i):
if ((arr[i] > arr[j]) and
(findSum(L[i]) < findSum(L[j]))):
for e in L[j]:
if e not in L[i]:
L[i].append(e)
L[i].append(arr[i])
res = L[ 0 ]
for x in L:
if (findSum(x) > findSum(res)):
res = x
for i in res:
print (i, end = " " )
arr = [ 3 , 2 , 6 , 4 , 5 , 1 ]
n = len (arr)
printMaxSumIS(arr, n)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int findSum(List< int > arr)
{
int sum = 0;
foreach ( int i in arr) sum += i;
return sum;
}
static void printMaxSumIs( int [] arr, int n)
{
List< int >[] L = new List< int >[ n ];
for ( int i = 0; i < n; i++)
L[i] = new List< int >();
L[0].Add(arr[0]);
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < i; j++) {
if ((arr[i] > arr[j])
&& (findSum(L[i]) < findSum(L[j]))) {
foreach ( int k in
L[j]) if (!L[i].Contains(k))
L[i]
.Add(k);
}
}
L[i].Add(arr[i]);
}
List< int > res = new List< int >(L[0]);
foreach (List< int > x in L) if (findSum(x)
> findSum(res)) res
= x;
foreach ( int i in res) Console.Write(i + " " );
Console.WriteLine();
}
public static void Main(String[] args)
{
int [] arr = { 3, 2, 6, 4, 5, 1 };
int n = arr.Length;
printMaxSumIs(arr, n);
}
}
|
Javascript
<script>
function findSum(arr)
{
let sum = 0;
for (let i=0;i<arr.length;i++)
sum += arr[i];
return sum;
}
function printMaxSumIs(arr,n)
{
let L = new Array(n);
for (let i = 0; i < n; i++)
L[i] = [];
L[0].push(arr[0]);
for (let i = 1; i < n; i++) {
for (let j = 0; j < i; j++) {
if ((arr[i] > arr[j])
&& (findSum(L[i]) < findSum(L[j])))
{
for (let k=0;k<L[j].length;k++)
if (!L[i].includes(L[j][k]))
L[i].push(L[j][k]);
}
}
L[i].push(arr[i]);
}
let res = L[0];
for (let x=0;x<L.length;x++)
if (findSum(L[x]) > findSum(res))
res = L[x];
for (let i=0;i<res.length;i++)
document.write(res[i] + " " );
document.write( "<br>" );
}
let arr=[3, 2, 6, 4, 5, 1];
let n = arr.length;
printMaxSumIs(arr, n);
</script>
|
We can optimize the above DP solution by removing findSum() function. Instead, we can maintain another vector/array to store sum of maximum sum increasing subsequence that ends with arr[i]. The implementation can be seen here.
Time complexity of above Dynamic Programming solution is O(n2).
Auxiliary space used by the program is O(n2).
Approach 2: (Using Dynamic Programming Using O(N) space
The above approach covered how to construct a Maximum Sum Increasing Subsequence in O(N2) time and O(N2) space. In this approach, we will optimize the Space complexity and construct the Maximum Sum Increasing Subsequence in O(N2) time and O(N) space.
- Let arr[0..n-1] be the input array.
- We define a vector of pairs L such that L[i] first stores the Maximum Sum Increasing Subsequence of arr[0..i] that ends with arr[i] and L[i].second stores the index of the previous element used for generating the sum.
- As the first element does not have any previous element hence its index would be -1 in L[0].
For example,
array = [3, 2, 6, 4, 5, 1]
L[0]: {3, -1}
L[1]: {2, 1}
L[2]: {9, 0}
L[3]: {7, 0}
L[4]: {12, 3}
L[5]: {1, 5}
As we can see above, the value of the Maximum Sum Increasing Subsequence is 12. To construct the actual Subsequence we will use the index stored in L[i].second. The steps to construct the Subsequence is shown below:
- In a vector result, store the value of the element where the Maximum Sum Increasing Subsequence was found (i.e at currIndex = 4). So in the result vector, we will add arr[currIndex].
- Update the currIndex to L[currIndex].second and repeat step 1 until currIndex is not -1 or it does not changes (i.e currIndex == previousIndex).
- Display the elements of the result vector in reverse order.
Below is the implementation of the above idea :
C++14
#include <bits/stdc++.h>
using namespace std;
void constructMaxSumIS(vector< int > arr, int n)
{
vector<pair< int , int > > L(n);
int index = 0;
for ( int i : arr) {
L[index] = { i, index };
index++;
}
L[0].second = -1;
for ( int i = 1; i < n; i++) {
for ( int j = 0; j < i; j++) {
if (arr[i] > arr[j]
and L[i].first < arr[i] + L[j].first) {
L[i].first = arr[i] + L[j].first;
L[i].second = j;
}
}
}
int maxi = INT_MIN, currIndex, track = 0;
for ( auto p : L) {
if (p.first > maxi) {
maxi = p.first;
currIndex = track;
}
track++;
}
vector< int > result;
int prevoiusIndex;
while (currIndex >= 0) {
result.push_back(arr[currIndex]);
prevoiusIndex = L[currIndex].second;
if (currIndex == prevoiusIndex)
break ;
currIndex = prevoiusIndex;
}
for ( int i = result.size() - 1; i >= 0; i--)
cout << result[i] << " " ;
}
int main()
{
vector< int > arr = { 1, 101, 2, 3, 100, 4, 5 };
int n = arr.size();
constructMaxSumIS(arr, n);
return 0;
}
|
Java
import java.util.*;
import java.awt.Point;
class GFG{
static void constructMaxSumIS(List<Integer> arr, int n)
{
List<Point> L = new ArrayList<Point>();
int index = 0 ;
for ( int i : arr)
{
L.add( new Point(i, index));
index++;
}
L.set( 0 , new Point(L.get( 0 ).x, - 1 ));
for ( int i = 1 ; i < n; i++)
{
for ( int j = 0 ; j < i; j++)
{
if (arr.get(i) > arr.get(j) &&
L.get(i).x < arr.get(i) +
L.get(j).x)
{
L.set(i, new Point(arr.get(i) +
L.get(j).x, j));
}
}
}
int maxi = - 100000000 , currIndex = 0 , track = 0 ;
for (Point p : L)
{
if (p.x > maxi)
{
maxi = p.x;
currIndex = track;
}
track++;
}
List<Integer> result = new ArrayList<Integer>();
int prevoiusIndex;
while (currIndex >= 0 )
{
result.add(arr.get(currIndex));
prevoiusIndex = L.get(currIndex).y;
if (currIndex == prevoiusIndex)
break ;
currIndex = prevoiusIndex;
}
for ( int i = result.size() - 1 ; i >= 0 ; i--)
System.out.print(result.get(i) + " " );
}
public static void main(String []s)
{
List<Integer> arr = new ArrayList<Integer>();
arr.add( 1 );
arr.add( 101 );
arr.add( 2 );
arr.add( 3 );
arr.add( 100 );
arr.add( 4 );
arr.add( 5 );
int n = arr.size();
constructMaxSumIS(arr, n);
}
}
|
Python3
import sys
def constructMaxSumIS(arr, n) :
L = []
index = 0
for i in arr :
L.append([i, index])
index + = 1
L[ 0 ][ 1 ] = - 1
for i in range ( 1 , n) :
for j in range (i) :
if (arr[i] > arr[j] and L[i][ 0 ] < arr[i] + L[j][ 0 ]) :
L[i][ 0 ] = arr[i] + L[j][ 0 ]
L[i][ 1 ] = j
maxi, currIndex, track = - sys.maxsize, 0 , 0
for p in L :
if (p[ 0 ] > maxi) :
maxi = p[ 0 ]
currIndex = track
track + = 1
result = []
while (currIndex > = 0 ) :
result.append(arr[currIndex])
prevoiusIndex = L[currIndex][ 1 ]
if (currIndex = = prevoiusIndex) :
break
currIndex = prevoiusIndex
for i in range ( len (result) - 1 , - 1 , - 1 ) :
print (result[i] , end = " " )
arr = [ 1 , 101 , 2 , 3 , 100 , 4 , 5 ]
n = len (arr)
constructMaxSumIS(arr, n)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static void constructMaxSumIS(List< int > arr, int n)
{
List<Tuple< int , int >> L = new List<Tuple< int , int >>();
int index = 0;
foreach ( int i in arr) {
L.Add( new Tuple< int , int >(i, index));
index++;
}
L[0] = new Tuple< int , int >(L[0].Item1, -1);
for ( int i = 1; i < n; i++)
{
for ( int j = 0; j < i; j++)
{
if (arr[i] > arr[j] &&
L[i].Item1 < arr[i] +
L[j].Item1)
{
L[i] = new Tuple< int ,
int >(arr[i] + L[j].Item1, j);
}
}
}
int maxi = Int32.MinValue,
currIndex = 0, track = 0;
foreach (Tuple< int , int > p in L)
{
if (p.Item1 > maxi)
{
maxi = p.Item1;
currIndex = track;
}
track++;
}
List< int > result = new List< int >();
int prevoiusIndex;
while (currIndex >= 0)
{
result.Add(arr[currIndex]);
prevoiusIndex = L[currIndex].Item2;
if (currIndex == prevoiusIndex)
break ;
currIndex = prevoiusIndex;
}
for ( int i = result.Count - 1; i >= 0; i--)
Console.Write(result[i] + " " );
}
static void Main()
{
List< int > arr = new List< int >( new
int [] { 1, 101, 2, 3, 100, 4, 5 });
int n = arr.Count;
constructMaxSumIS(arr, n);
}
}
|
Javascript
<script>
function constructMaxSumIS(arr, n){
let L = []
let index = 0
for (let i of arr){
L.push([i, index])
index += 1
}
L[0][1] = -1
for (let i=1;i<n;i++){
for (let j=0;j<i;j++){
if (arr[i] > arr[j] && L[i][0] < arr[i] + L[j][0]){
L[i][0] = arr[i] + L[j][0]
L[i][1] = j
}
}
}
let maxi = Number.MIN_VALUE, currIndex = 0, track = 0
for (let p of L){
if (p[0] > maxi){
maxi = p[0]
currIndex = track
}
track += 1
}
let result = []
while (currIndex >= 0){
result.push(arr[currIndex])
let prevoiusIndex = L[currIndex][1]
if (currIndex == prevoiusIndex)
break
currIndex = prevoiusIndex
}
for (let i=result.length - 1;i>=0;i--)
document.write(result[i] , " " )
}
let arr = [ 1, 101, 2, 3, 100, 4, 5 ]
let n = arr.length
constructMaxSumIS(arr, n)
</script>
|
Time Complexity: O(N2)
Space Complexity: O(N)
Share your thoughts in the comments
Please Login to comment...