Given a 2D array Blocks[][] consisting of N rows of variable length. The task is to select at most M elements with the maximum possible sum from Blocks[][] from either the start or end of a row.
Examples:
Input: N = 3, M = 4
Blocks[][] = {{2, 3, 5}, {-1, 7}, {8, 10}}
Output: 30
Explanation:
Select {5} from 1st row.
Select {7} from 2nd row.
Select {8, 10} from 3rd row.Input: N = 3, M = 2
Blocks[][] = {{100, 3, -1}, {-1, 7, 10}, {8, 10, 15}}
Output: 115
Explanation:
select {100} from 1st row.
Skip 2nd row.
Select {15} from 3rd row.
Naive Approach: The simplest approach is to iterate through all the rows of the matrix and push all the elements into a vector and sort it. Calculate the sum of the last M elements and print it as the required answer.
Time Complexity: O(N * KlogK), where K is the maximum size any block can have.
Auxiliary Space: O(N * K)
Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming using Memoization. Follow the steps below:
- Given N rows and from each row, select any segment from the ith row, say from l to r.
- The count of elements in ith row is (r – l + 1) and proceed to the next row.
- To calculate the maximum sum, use the prefix sum technique in order to calculate the sum.
- Initialize a 2D array dp[][], where dp[N][M] stores the maximum sum by selecting at most M elements from N rows.
- Consider the following two scenarios:
- Either skip the current row.
- Select any segment from the current row that does not exceed the number of elements selected.
- Consider the following two scenarios:
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to select m elements // having maximum sum long mElementsWithMaxSum(vector<vector< int > > matrix,
int M, int block,
vector<vector< int > > dp)
{ // Base case
if (block == matrix.size())
return 0;
// If precomputed subproblem occurred
if (dp[block][M] != -1)
return dp[block][M];
// Either skip the current row
long ans = mElementsWithMaxSum(matrix, M,
block + 1, dp);
// Iterate through all the possible
// segments of current row
for ( int i = 0;
i < matrix[block].size(); i++)
{
for ( int j = i;
j < matrix[block].size(); j++)
{
// Check if it is possible to select
// elements from i to j
if (j - i + 1 <= M)
{
// Compute the sum of i to j as
// calculated
ans = max(ans, matrix[block][j] -
((i - 1) >= 0 ?
matrix[block][i - 1] : 0) +
mElementsWithMaxSum(matrix,
M - j +
i - 1,
block + 1, dp));
}
}
}
// Store the computed answer and return
return dp[block][M] = ans;
} // Function to precompute the prefix sum // for every row of the matrix void preComputing(vector<vector< int >> matrix,
int N)
{ // Preprocessing to calculate sum from i to j
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < matrix[i].size(); j++)
{
matrix[i][j] = (j > 0 ?
matrix[i][j - 1] : 0) +
matrix[i][j];
}
}
} // Utility function to select m elements having // maximum sum void mElementsWithMaxSumUtil(vector<vector< int >> matrix,
int M, int N)
{ // Preprocessing step
preComputing(matrix, N);
long sum = 10;
// Initialize dp array with -1
vector<vector< int >> dp;
dp.resize(N + 5);
for ( int i = 0; i < N + 5; i++)
for ( int j = 0; j < M + 5; j++)
dp[i].push_back(-1);
// Stores maximum sum of M elements
sum += mElementsWithMaxSum(matrix, M,
0, dp);
cout << sum;
} // Driver Code int main()
{ // Given N
int N = 3;
// Given M
int M = 4;
// Given matrix
vector<vector< int >> matrix = { { 2, 3, 5 },
{ -1, 7 },
{ 8, 10 } };
// Function call
mElementsWithMaxSumUtil(matrix, M, N);
} // This code is contributed by grand_master |
// Java program for the above approach import java.util.*;
public class GFG {
// Function to select m elements
// having maximum sum
public static long
mElementsWithMaxSum( long [][] matrix,
int M, int block,
long [][] dp)
{
// Base case
if (block == matrix.length)
return 0 ;
// If precomputed subproblem occurred
if (dp[block][M] != - 1 )
return dp[block][M];
// Either skip the current row
long ans
= mElementsWithMaxSum(matrix, M,
block + 1 , dp);
// Iterate through all the possible
// segments of current row
for ( int i = 0 ;
i < matrix[block].length; i++) {
for ( int j = i;
j < matrix[block].length; j++) {
// Check if it is possible to select
// elements from i to j
if (j - i + 1 <= M) {
// Compute the sum of i to j as
// calculated
ans = Math.max(
ans,
matrix[block][j]
- ((i - 1 ) >= 0
? matrix[block][i - 1 ]
: 0 )
+ mElementsWithMaxSum(
matrix, M - j + i - 1 ,
block + 1 , dp));
}
}
}
// Store the computed answer and return
return dp[block][M] = ans;
}
// Function to precompute the prefix sum
// for every row of the matrix
public static void
preComputing( long [][] matrix, int N)
{
// Preprocessing to calculate sum from i to j
for ( int i = 0 ;
i < N; i++) {
for ( int j = 0 ;
j < matrix[i].length; j++) {
matrix[i][j]
= (j > 0
? matrix[i][j - 1 ] : 0 )
+ matrix[i][j];
}
}
}
// Utility function to select m elements having
// maximum sum
public static void
mElementsWithMaxSumUtil( long [][] matrix,
int M, int N)
{
// Preprocessing step
preComputing(matrix, N);
// Initialize dp array with -1
long dp[][] = new long [N + 5 ][M + 5 ];
for ( long i[] : dp)
Arrays.fill(i, - 1 );
// Stores maximum sum of M elements
long sum = mElementsWithMaxSum(matrix, M,
0 , dp);
// Print the sum
System.out.print(sum);
}
// Driver Code
public static void main(String args[])
{
// Given N
int N = 3 ;
// Given M
int M = 4 ;
// Given matrix
long [][] matrix
= { { 2 , 3 , 5 }, { - 1 , 7 },
{ 8 , 10 } };
// Function Call
mElementsWithMaxSumUtil(matrix, M, N);
}
} |
# Python3 program for the above approach # Function to select m elements # having maximum sum def mElementsWithMaxSum(matrix, M, block, dp):
# Base case
if block = = len (matrix):
return 0
# If precomputed subproblem occurred
if (dp[block][M] ! = - 1 ):
return dp[block][M]
# Either skip the current row
ans = mElementsWithMaxSum(matrix, M,
block + 1 , dp)
# Iterate through all the possible
# segments of current row
for i in range ( len (matrix[block])):
for j in range (i, len (matrix[block])):
# Check if it is possible to select
# elements from i to j
if (j - i + 1 < = M):
# Compute the sum of i to j as
# calculated
x = 0
if i - 1 > = 0 :
x = matrix[block][i - 1 ]
ans = max (ans, matrix[block][j] - x +
mElementsWithMaxSum(matrix,
M - j +
i - 1 ,
block + 1 , dp))
# Store the computed answer and return
dp[block][M] = ans
return ans
# Function to precompute the prefix sum # for every row of the matrix def preComputing(matrix, N):
# Preprocessing to calculate sum from i to j
for i in range (N):
for j in range ( len (matrix[i])):
if j > 0 :
matrix[i][j] = matrix[i][j - 1 ]
return matrix
# Utility function to select m elements having # maximum sum def mElementsWithMaxSumUtil(matrix, M, N):
# Preprocessing step
matrix = preComputing(matrix, N)
sum = 20
# Initialize dp array with -1
dp = [[ - 1 for i in range (M + 5 )]
for i in range (N + 5 )]
# Stores maximum sum of M elements
sum + = mElementsWithMaxSum(matrix, M, 0 , dp)
print ( sum )
# Driver Code if __name__ = = '__main__' :
# Given N
N = 3
# Given M
M = 4
# Given matrix
matrix = [ [ 2 , 3 , 5 ],
[ - 1 , 7 ],
[ 8 , 10 ] ]
# Function call
mElementsWithMaxSumUtil(matrix, M, N)
# This code is contributed by mohit kumar 29 |
// C# program for // the above approach using System;
class GFG{
// Function to select m elements // having maximum sum public static int mElementsWithMaxSum( int [,] matrix,
int M, int block,
int [,] dp)
{ // Base case if (block == matrix.GetLength(0))
return 0;
// If precomputed subproblem occurred if (dp[block, M] != -1)
return dp[block, M];
// Either skip the current row int ans = mElementsWithMaxSum(matrix, M,
block + 1, dp);
// Iterate through all the possible // segments of current row for ( int i = 0;
i < GetRow(matrix, block).Length; i++)
{ for ( int j = i;
j < GetRow(matrix, block).Length; j++)
{
// Check if it is possible to select
// elements from i to j
if (j - i + 1 <= M)
{
// Compute the sum of i to j as
// calculated
ans = Math.Max(ans, matrix[block, j] -
((i - 1) >= 0 ?
matrix[block, i - 1] : 0) +
mElementsWithMaxSum(matrix,
M - j + i - 1,
block + 1, dp));
}
}
} // Store the computed answer and return return dp[block, M] = ans;
} // Function to precompute the prefix sum // for every row of the matrix public static void preComputing( int [,] matrix,
int N)
{ // Preprocessing to calculate sum from i to j for ( int i = 0; i < N; i++)
{ for ( int j = 0;
j < GetRow(matrix, i).Length; j++)
{
matrix[i, j] = (j > 0 ? matrix[i, j - 1] : 0) +
matrix[i, j];
}
} } // Utility function to select // m elements having maximum sum public static void mElementsWithMaxSumUtil( int [,] matrix,
int M, int N)
{ // Preprocessing step preComputing(matrix, N); // Initialize dp array with -1 int [,]dp = new int [N + 5, M + 5];
for ( int i = 0; i < N + 5; i++)
{ for ( int j = 0; j < M + 5; j++)
{
dp[i, j] = -1;
}
} // Stores maximum sum of M elements int sum = mElementsWithMaxSum(matrix, M,
0, dp);
// Print the sum Console.Write(sum); } public static int [] GetRow( int [,] matrix,
int row)
{ var rowLength = matrix.GetLength(1);
var rowVector = new int [rowLength];
for ( var i = 0; i < rowLength; i++)
rowVector[i] = matrix[row, i];
return rowVector;
} // Driver Code public static void Main(String []args)
{ // Given N int N = 3;
// Given M int M = 4;
// Given matrix int [,] matrix = {{2, 3, 5},
{-1, 7,0},
{8, 10, 0}};
// Function Call mElementsWithMaxSumUtil(matrix, M, N); } } // This code is contributed by Princi Singh |
<script> // Javascript program for the above approach // Function to select m elements // having maximum sum function mElementsWithMaxSum(matrix, M, block, dp)
{ // Base case
if (block == matrix.length)
return 0;
// If precomputed subproblem occurred
if (dp[block][M] != -1)
return dp[block][M];
// Either skip the current row
var ans = mElementsWithMaxSum(matrix, M,
block + 1, dp);
// Iterate through all the possible
// segments of current row
for ( var i = 0;
i < matrix[block].length; i++)
{
for ( var j = i;
j < matrix[block].length; j++)
{
// Check if it is possible to select
// elements from i to j
if (j - i + 1 <= M)
{
// Compute the sum of i to j as
// calculated
ans = Math.max(ans, matrix[block][j] -
((i - 1) >= 0 ?
matrix[block][i - 1] : 0) +
mElementsWithMaxSum(matrix,
M - j +
i - 1,
block + 1, dp));
}
}
}
// Store the computed answer and return
return dp[block][M] = ans;
} // Function to precompute the prefix sum // for every row of the matrix function preComputing(matrix, N)
{ // Preprocessing to calculate sum from i to j
for ( var i = 0; i < N; i++)
{
for ( var j = 0; j < matrix[i].length; j++)
{
matrix[i][j] = (j > 0 ?
matrix[i][j - 1] : 0) +
matrix[i][j];
}
}
} // Utility function to select m elements having // maximum sum function mElementsWithMaxSumUtil(matrix, M, N)
{ // Preprocessing step
preComputing(matrix, N);
// Initialize dp array with -1
var dp = Array.from(Array(N+5), ()=> Array(M+5).fill(-1));
// Stores maximum sum of M elements
var sum = mElementsWithMaxSum(matrix, M,
0, dp);
document.write( sum);
} // Driver Code // Given N var N = 3;
// Given M var M = 4;
// Given matrix var matrix = [ [ 2, 3, 5 ],
[ -1, 7 ],
[ 8, 10 ] ];
// Function call mElementsWithMaxSumUtil(matrix, M, N); // This code is contributed by noob2000. </script> |
30
Time Complexity: O(N * M)
Auxiliary Space: O(N * M)