Maximise sum of product of pairs by choosing subsequence of same length from given Arrays
Given two integer arrays A[] and B[] of different length N and M respectively, the task is to choose any subsequence of same length from each array such that sum of product of pairs at corresponding indices in the subsequence is maximised.
Example:
Input: A = {4, -1, -3, 3}, B = {-4, 0, 5}
Output: 27
Explanation: Choosing subsequence {-3, 3} from A and subsequence {-4, 5} from B will give the maximum sum,
i.e. = (-3)*(-4) + 3*5 = 12 + 15 = 27
Input: A = {-5, -1}, B = {2, 1, 4}
Output: -1
Explanation: The maximum sum of products possible is (-1)*1 = -1
Naive Approach: When carefully observed, actually we need to find optimal subsequences of equal length (>=1) from each array, such that summation of the products of elements from these subsequences is maximum.
So by using hit and trial method, we can use a recursive approach with to “choose or not choose” each element from both arrays, and find the optimal subsequence from all possible subsequences.
Below is the implementation of the recursive approach.
C++
#include <bits/stdc++.h>
using namespace std;
int MaxSOP(vector< int >& a, vector< int >& b,
int n, int m,
int taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0)
&& taken != 0)
return 0;
return max(
{ a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1,
m - 1, taken + 1),
MaxSOP(a, b, n - 1, m, taken),
MaxSOP(a, b, n, m - 1, taken) });
}
int main()
{
vector< int > a = { 4, -1, -3, 3 };
vector< int > b = { -4, 0, 5 };
int ans = MaxSOP(a, b, a.size(),
b.size(), 0);
cout << ans << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
public static int MaxSOP( int a[], int b[], int n, int m,
int taken)
{
if ((n == 0 || m == 0 ) && taken == 0 )
return - 9999999 ;
else if ((n == 0 || m == 0 ) && taken != 0 )
return 0 ;
return Math.max(
Math.max(
a[n - 1 ] * b[m - 1 ]
+ MaxSOP(a, b, n - 1 , m - 1 , taken + 1 ),
MaxSOP(a, b, n - 1 , m, taken)),
MaxSOP(a, b, n, m - 1 , taken));
}
public static void main(String[] args)
{
int a[] = { 4 , - 1 , - 3 , 3 };
int b[] = { - 4 , 0 , 5 };
int ans = MaxSOP(a, b, a.length, b.length, 0 );
System.out.print(ans);
}
}
|
Python3
def MaxSOP(a, b, n, m, taken):
if ((n = = 0 or m = = 0 ) and taken = = 0 ):
return - 9999999
elif ((n = = 0 or m = = 0 ) and taken ! = 0 ):
return 0
return max (a[n - 1 ] * b[m - 1 ] + MaxSOP(a, b, n - 1 ,m - 1 , taken + 1 ),MaxSOP(a, b, n - 1 , m, taken),MaxSOP(a, b, n, m - 1 , taken))
a = [ 4 , - 1 , - 3 , 3 ]
b = [ - 4 , 0 , 5 ]
ans = MaxSOP(a, b, len (a), len (b), 0 )
print (ans)
|
C#
using System;
class GFG {
static int MaxSOP( int [] a, int [] b, int n, int m,
int taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0) && taken != 0)
return 0;
return Math.Max(
a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1, m - 1, taken + 1),
Math.Max(MaxSOP(a, b, n - 1, m, taken),
MaxSOP(a, b, n, m - 1, taken)));
}
public static void Main()
{
int [] a = { 4, -1, -3, 3 };
int [] b = { -4, 0, 5 };
int ans = MaxSOP(a, b, a.Length, b.Length, 0);
Console.Write(ans);
}
}
|
Javascript
<script>
function MaxSOP(a, b, n, m, taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0)
&& taken != 0)
return 0;
return Math.max(a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1,
m - 1, taken + 1),
MaxSOP(a, b, n - 1, m, taken),
MaxSOP(a, b, n, m - 1, taken));
}
let a = [ 4, -1, -3, 3 ]
let b = [ -4, 0, 5 ]
let ans = MaxSOP(a, b, a.length, b.length, 0)
document.write(ans, "</br>" )
</script>
|
Time Complexity: O(3N), as we are calling the function 3 times.
Auxiliary Space: O(1) (Recursion stack is not taken into consideration)
Efficient Approach: The exponential time complexity of Naive approach, due to recursion, can be optimized with Dynamic programming.
Memoize the recursive code and store the results in a matrix, so that when an overlapping sub-problem is found, directly return the result of it from the matrix. This will reduce the depth of the recursion and reduce the time complexity.
As we have three changing parameters, we will require 3D DP-array to store the values
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int t[101][101][101];
int MaxSOP(vector< int >& a, vector< int >& b,
int n, int m,
int taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0) && taken != 0)
return 0;
if (t[n][m][taken] != -1)
return t[n][m][taken];
return t[n][m][taken]
= max({ a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1,
m - 1,
taken + 1),
MaxSOP(a, b, n - 1, m, taken),
MaxSOP(a, b, n, m - 1, taken) });
}
int main()
{
vector< int > a = { 4, -1, -3, 3 };
vector< int > b = { -4, 0, 5 };
memset (t, -1, sizeof (t));
int ans = MaxSOP(a, b, a.size(),
b.size(), 0);
cout << ans << endl;
return 0;
}
|
Java
import java.util.*;
public class GFG {
static int t[][][] = new int [ 101 ][ 101 ][ 101 ];
static int MaxSOP( int [] a, int [] b, int n, int m,
int taken)
{
if ((n == 0 || m == 0 ) && taken == 0 )
return - 9999999 ;
else if ((n == 0 || m == 0 ) && taken != 0 )
return 0 ;
if (t[n][m][taken] != - 1 )
return t[n][m][taken];
return t[n][m][taken]
= Math.max(
a[n - 1 ] * b[m - 1 ]
+ MaxSOP(a, b, n - 1 , m - 1 , taken + 1 ),
Math.max(MaxSOP(a, b, n - 1 , m, taken),
MaxSOP(a, b, n, m - 1 , taken)));
}
public static void main(String args[])
{
int [] a = { 4 , - 1 , - 3 , 3 };
int [] b = { - 4 , 0 , 5 };
for ( int i = 0 ; i < 101 ; i++) {
for ( int j = 0 ; j < 101 ; j++) {
for ( int k = 0 ; k < 101 ; k++) {
t[i][j][k] = - 1 ;
}
}
}
int ans = MaxSOP(a, b, a.length, b.length, 0 );
System.out.println(ans);
}
}
|
Python3
t = [[ [ - 1 for col in range ( 101 )] for col in range ( 101 )] for row in range ( 101 )]
def MaxSOP(a, b, n, m, taken):
global t
if ((n = = 0 or m = = 0 ) and taken = = 0 ):
return - 9999999
elif ((n = = 0 or m = = 0 ) and taken ! = 0 ):
return 0
if (t[n][m][taken] ! = - 1 ):
return t[n][m][taken]
t[n][m][taken] = max ( max (a[n - 1 ] * b[m - 1 ] + MaxSOP(a, b, n - 1 ,m - 1 ,taken + 1 ),MaxSOP(a, b, n - 1 , m, taken)),MaxSOP(a, b, n, m - 1 , taken))
return t[n][m][taken]
a = [ 4 , - 1 , - 3 , 3 ]
b = [ - 4 , 0 , 5 ]
ans = MaxSOP(a, b, len (a), len (b), 0 )
print (ans)
|
C#
using System;
class GFG {
static int [, , ] t = new int [101, 101, 101];
static int MaxSOP( int [] a, int [] b, int n, int m,
int taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0) && taken != 0)
return 0;
if (t[n, m, taken] != -1)
return t[n, m, taken];
return t[n, m, taken]
= Math.Max(
a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1, m - 1, taken + 1),
Math.Max(MaxSOP(a, b, n - 1, m, taken),
MaxSOP(a, b, n, m - 1, taken)));
}
public static void Main()
{
int [] a = { 4, -1, -3, 3 };
int [] b = { -4, 0, 5 };
for ( int i = 0; i < 101; i++) {
for ( int j = 0; j < 101; j++) {
for ( int k = 0; k < 101; k++) {
t[i, j, k] = -1;
}
}
}
int ans = MaxSOP(a, b, a.Length, b.Length, 0);
Console.WriteLine(ans);
}
}
|
Javascript
<script>
let t = new Array(101);
for (let i = 0; i < 101; i++){
t[i] = new Array(101);
for (let j = 0; j < 101; j++){
t[i][j] = new Array(101).fill(-1);
}
}
function MaxSOP(a, b, n, m, taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0) && taken != 0)
return 0;
if (t[n][m][taken] != -1)
return t[n][m][taken];
return t[n][m][taken]
= Math.max(Math.max(a[n - 1] * b[m - 1]+ MaxSOP(a, b, n - 1, m - 1,taken + 1),MaxSOP(a, b, n - 1, m, taken)),MaxSOP(a, b, n, m - 1, taken));
}
let a = [ 4, -1, -3, 3 ];a
let b = [ -4, 0, 5 ];
let ans = MaxSOP(a, b, a.length, b.length, 0);
document.write(ans);
</script>
|
Time Complexity: O(N3).
Auxiliary Space: O(N3), for using the extra 3D array.
More Efficient Approach: This above approach can be further optimized by reducing the state taken using the following observation:
In the above dynamic programming approach, we are concerned with only two states of taken: either 0 or not 0.
So instead of keeping multiple states of taken, it can be bound to two states 0 and 1.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int t[101][101][2];
int MaxSOP(vector< int >& a, vector< int >& b,
int n, int m, int taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0) && taken != 0)
return 0;
if (t[n][m][taken == 0 ? 0 : 1] != -1)
return t[n][m][taken == 0 ? 0 : 1];
return t[n][m][taken == 0 ? 0 : 1]
= max({ a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1, m - 1,
taken + 1),
MaxSOP(a, b, n - 1, m, taken),
MaxSOP(a, b, n, m - 1, taken) });
}
int main()
{
vector< int > a = { 4, -1, -3, 3 };
vector< int > b = { -4, 0, 5 };
memset (t, -1, sizeof (t));
int ans = MaxSOP(a, b, a.size(), b.size(), 0);
cout << ans << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
static int t[][][] = new int [ 101 ][ 101 ][ 101 ];
static int MaxSOP( int [] a, int [] b, int n, int m,
int taken)
{
if ((n == 0 || m == 0 ) && taken == 0 )
return - 9999999 ;
else if ((n == 0 || m == 0 ) && taken != 0 )
return 0 ;
if (t[n][m][taken == 0 ? 0 : 1 ] != - 1 )
return t[n][m][taken == 0 ? 0 : 1 ];
return t[n][m][taken == 0 ? 0 : 1 ]
= Math.max(
a[n - 1 ] * b[m - 1 ]
+ MaxSOP(a, b, n - 1 , m - 1 , taken + 1 ),
Math.max(MaxSOP(a, b, n - 1 , m, taken),
MaxSOP(a, b, n, m - 1 , taken)));
}
public static void main(String args[])
{
int [] a = { 4 , - 1 , - 3 , 3 };
int [] b = { - 4 , 0 , 5 };
for ( int i = 0 ; i < 101 ; i++) {
for ( int j = 0 ; j < 101 ; j++) {
for ( int k = 0 ; k < 101 ; k++) {
t[i][j][k] = - 1 ;
}
}
}
int ans = MaxSOP(a, b, a.length, b.length, 0 );
System.out.println(ans);
}
}
|
Python3
import math
t = [[[ 0 ] * 101 ] * 101 ] * 101
def MaxSOP(a, b, n, m, taken):
if ((n = = 0 or m = = 0 ) and taken = = 0 ):
return - 9999999
elif ((n = = 0 or m = = 0 ) and taken ! = 0 ) :
return 0
if (t[n][m][ 0 if taken = = 0 else 1 ] ! = - 1 ):
return t[n][m][ 0 if taken = = 0 else 1 ]
return max (a[n - 1 ] * b[m - 1 ] + MaxSOP(a, b, n - 1 , m - 1 , taken + 1 ), max (MaxSOP(a, b, n - 1 , m, taken), MaxSOP(a, b, n, m - 1 , taken)))
if __name__ = = "__main__" :
a = [ 4 , - 1 , - 3 , 3 ]
b = [ - 4 , 0 , 5 ]
for i in range ( 101 ) :
for j in range ( 101 ) :
for k in range ( 101 ) :
t[i][j][k] = - 1
ans = MaxSOP(a, b, len (a), len (b), 0 )
print (ans)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int [, , ] t = new int [101, 101, 2];
static int MaxSOP(List< int > a, List< int > b, int n,
int m, int taken)
{
if ((n == 0 || m == 0) && taken == 0)
return -9999999;
else if ((n == 0 || m == 0) && taken != 0)
return 0;
if (t[n, m, taken == 0 ? 0 : 1] != -1)
return t[n, m, taken == 0 ? 0 : 1];
return t[n, m, taken == 0 ? 0 : 1] = Math.Max(
Math.Max(a[n - 1] * b[m - 1]
+ MaxSOP(a, b, n - 1, m - 1,
taken + 1),
MaxSOP(a, b, n - 1, m, taken)),
MaxSOP(a, b, n, m - 1, taken));
}
public static void Main()
{
List< int > a = new List< int >() { 4, -1, -3, 3 };
List< int > b = new List< int >() { -4, 0, 5 };
for ( int i = 0; i < 101; i++)
for ( int j = 0; j < 101; j++)
for ( int k = 0; k < 2; k++)
t[i, j, k] = -1;
int ans = MaxSOP(a, b, a.Count, b.Count, 0);
Console.Write(ans);
}
}
|
Javascript
<script>
let t = new Array(101);
for (let i = 0; i < 101; i++)
{
t[i] = new Array(101);
for (let j = 0; j < 101; j++)
{
t[i][j] = new Array(2).fill(0);
}
}
function MaxSOP(a, b, n, m, taken){
if ((n == 0 || m == 0) && taken == 0)
return -9999999
else if ((n == 0 || m == 0) && taken != 0)
return 0
if (t[n][m][taken == 0 ? 0 : 1] != -1)
return t[n][m][taken == 0 ? 0 : 1]
return Math.max(a[n - 1] * b[m - 1] + MaxSOP(a, b, n - 1, m - 1, taken + 1), Math.max(MaxSOP(a, b, n - 1, m, taken), MaxSOP(a, b, n, m - 1, taken)))
}
let a = [ 4, -1, -3, 3 ]
let b = [ -4, 0, 5 ]
for (let i = 0; i < 101; i++)
{
for (let j = 0; j < 101; j++)
{
for (let k = 0; k < 101; k++)
{
t[i][j][k] = -1
}
}
}
let ans = MaxSOP(a, b, a.length, b.length, 0)
document.write(ans)
</script>
|
Time Complexity: O(N*M)
Auxiliary Space: O(N*M)
Bottom Up Approach:
Above approach can be space optimized by using iterative method instead of using recursive method which is taking extra stack space.
Below is the implementation of the same approach in Bottom-Up Manner.
C++
#include <bits/stdc++.h>
using namespace std;
int MaxSOP(vector< int >& a, vector< int >& b, int n, int m) {
vector<vector<vector< int >>> dp(n + 1, vector<vector< int >>(m + 1, vector< int >(2, 0)));
for ( int i = 0; i <= n; i++) {
for ( int j = 0; j <= m; j++) {
dp[i][j][0] = -9999999;
dp[i][j][1] = 0;
}
}
for ( int i = 1; i <= n; i++) {
for ( int j = 1; j <= m; j++) {
dp[i][j][0] = max(a[i - 1] * b[j - 1] + dp[i - 1][j - 1][1], max(dp[i - 1][j][0], dp[i][j - 1][0]));
dp[i][j][1] = max(a[i - 1] * b[j - 1] + dp[i - 1][j - 1][0], max(dp[i - 1][j][1], dp[i][j - 1][1]));
}
}
return max(dp[n][m][0], dp[n][m][1]);
}
int main() {
vector< int > a = {4, -1, -3, 3};
vector< int > b = {-4, 0, 5};
int ans = MaxSOP(a, b, a.size(), b.size());
cout << ans << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class MaxSOP {
public static int maxSOP( int [] a, int [] b)
{
int n = a.length;
int m = b.length;
int [][][] dp = new int [n + 1 ][m + 1 ][ 2 ];
for ( int i = 0 ; i <= n; i++) {
for ( int j = 0 ; j <= m; j++) {
if (i == 0 || j == 0 ) {
dp[i][j][ 0 ] = 0 ;
dp[i][j][ 1 ] = 0 ;
}
else {
dp[i][j][ 0 ] = Math.max(
a[i - 1 ] * b[j - 1 ]
+ dp[i - 1 ][j - 1 ][ 1 ],
Math.max(dp[i - 1 ][j][ 0 ],
dp[i][j - 1 ][ 0 ]));
dp[i][j][ 1 ] = Math.max(
a[i - 1 ] * b[j - 1 ]
+ dp[i - 1 ][j - 1 ][ 0 ],
Math.max(dp[i - 1 ][j][ 1 ],
dp[i][j - 1 ][ 1 ]));
}
}
}
return Math.max(dp[n][m][ 0 ], dp[n][m][ 1 ]);
}
public static void main(String[] args)
{
int [] a = { 4 , - 1 , - 3 , 3 };
int [] b = { - 4 , 0 , 5 };
int ans = maxSOP(a, b);
System.out.println(ans);
}
}
|
Python3
def max_sop(a, b):
n, m = len (a), len (b)
dp = [[[ 0 , 0 ] for _ in range (m + 1 )] for _ in range (n + 1 )]
for i in range ( 1 , n + 1 ):
for j in range ( 1 , m + 1 ):
dp[i][j][ 0 ] = max (a[i - 1 ] * b[j - 1 ] + dp[i - 1 ][j - 1 ][ 1 ], max (dp[i - 1 ][j][ 0 ], dp[i][j - 1 ][ 0 ]))
dp[i][j][ 1 ] = max (a[i - 1 ] * b[j - 1 ] + dp[i - 1 ][j - 1 ][ 0 ], max (dp[i - 1 ][j][ 1 ], dp[i][j - 1 ][ 1 ]))
return max (dp[n][m][ 0 ], dp[n][m][ 1 ])
a = [ 4 , - 1 , - 3 , 3 ]
b = [ - 4 , 0 , 5 ]
ans = max_sop(a, b)
print (ans)
|
C#
using System;
using System.Collections.Generic;
class Program {
static int MaxSOP(List< int > a, List< int > b, int n,
int m)
{
int [][][] dp = new int [n + 1][][];
for ( int i = 0; i <= n; i++) {
dp[i] = new int [m + 1][];
for ( int j = 0; j <= m; j++) {
dp[i][j] = new int [2];
dp[i][j][0]
= -9999999;
dp[i][j][1] = 0;
}
}
for ( int i = 1; i <= n; i++) {
for ( int j = 1; j <= m; j++) {
dp[i][j][0]
= Math.Max(a[i - 1] * b[j - 1]
+ dp[i - 1][j - 1][1],
Math.Max(dp[i - 1][j][0],
dp[i][j - 1][0]));
dp[i][j][1]
= Math.Max(a[i - 1] * b[j - 1]
+ dp[i - 1][j - 1][0],
Math.Max(dp[i - 1][j][1],
dp[i][j - 1][1]));
}
}
return Math.Max(dp[n][m][0], dp[n][m][1]);
}
static void Main()
{
List< int > a = new List< int >{ 4, -1, -3, 3 };
List< int > b = new List< int >{ -4, 0, 5 };
int ans = MaxSOP(a, b, a.Count, b.Count);
Console.WriteLine(ans);
}
}
|
Javascript
function maxSOP(a, b) {
const n = a.length;
const m = b.length;
const dp = new Array(n + 1).fill(0).map(() =>
new Array(m + 1).fill(0).map(() => [Number.MIN_SAFE_INTEGER, 0])
);
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
dp[i][j][0] = Math.max(
a[i - 1] * b[j - 1] + dp[i - 1][j - 1][1],
Math.max(dp[i - 1][j][0], dp[i][j - 1][0])
);
dp[i][j][1] = Math.max(
a[i - 1] * b[j - 1] + dp[i - 1][j - 1][0],
Math.max(dp[i - 1][j][1], dp[i][j - 1][1])
);
}
}
return Math.max(dp[n][m][0], dp[n][m][1]);
}
const a = [4, -1, -3, 3];
const b = [-4, 0, 5];
const result = maxSOP(a, b);
console.log(result);
|
Time Complexity: O(N*M)
Auxiliary Space: O(N*M)
Last Updated :
26 Dec, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...