Maximum possible score that can be obtained by constructing a Binary Tree based on given conditions
Last Updated :
26 Apr, 2023
Given an array arr[] of (N – 1) integers and each value arr[i](1-based indexing) is the score of the nodes having degree i. The task is to determine the maximum score of any tree of N nodes that can be constructed.
Examples:
Input: arr[] = {1, 3, 0}
Output: 8
Explanation:
One possible way to construct tree is:
1
/ \
2 3
\
4
Node 1 have degree 2. Therefore, its score is 3.
Node 2 have degree 1. Therefore, its score is 1.
Node 3 have degree 2. Therefore, its score is 3.
Node 4 have degree 1. Therefore, its score is 1.
Therefore, the total score = 3 + 1 + 3 + 1 = 8.
Input: arr[] = {0, 1}
Output: 1
Explanation:
One possible way to construct tree is:
1
/ \
2 3
Node 1 have degree 2. Therefore, its score is 1.
Node 2 have degree 1. Therefore, its score is 0.
Node 3 have degree 1. Therefore, its score is 0.
Therefore, total score = 1 + 0 + 0 = 1.
Naive Approach: The simplest approach is to generate all possible combinations of constructing a tree having N nodes and find the total score for each of them. Then, print the maximum of all the scores obtained.
Time Complexity: (N!) where N is the number of nodes in the tree.
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming by creating a dp[][] table where dp[i][j] represents the maximum score using i nodes having the sum of degrees of the nodes as j. Follow the below steps to solve the problem:
- Initialize an array dp[N + 1][2*(N – 1) + 1] where N is the number of nodes and (2*(N – 1)) is the maximum sum of degrees.
- Initialize dp[0][0] with 0.
- Iterate two nested loops, one over the range [1, N], and another for till the possible maximum score 2*(N – 1) from 1 and for each score s in the range [1, N] traverse the given array of scores arr[] and updating dp[i][s] as:
dp[i][s] = max(dp[i][s], scores[j-1] dp[i-1][s-j])
where dp[i][s] represents the maximum score of tree having i nodes and sum of degrees as s.
- For a tree with N vertices and (N – 1) edges, the sum of all degrees should be 2 * (N – 1). Therefore, print the value of dp[N][2*(N – 1)] as the maximum score for a tree with N nodes.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxScore(vector< int >& arr)
{
int N = arr.size();
N++;
vector<vector< int > >
dp(N + 1, vector< int >(2 * N,
-100000));
dp[0][0] = 0;
for ( int i = 1; i <= N; i++) {
for ( int s = 1;
s <= 2 * (N - 1); s++) {
for ( int j = 1; j <= N - 1
and j <= s;
j++) {
dp[i][s]
= max(dp[i][s],
arr[j - 1]
+ dp[i - 1][s - j]);
}
}
}
return dp[N][2 * (N - 1)];
}
int main()
{
vector< int > arr = { 1, 3, 0 };
cout << maxScore(arr);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int maxScore( int [] arr)
{
int N = arr.length;
N++;
int [][] dp = new int [N + 1 ][ 2 * (N - 1 ) + 1 ];
dp[ 0 ][ 0 ] = 0 ;
for ( int i = 1 ; i <= N; i++)
{
for ( int s = 1 ; s <= 2 * (N - 1 ); s++)
{
for ( int j = 1 ; j <= N - 1 && j <= s; j++)
{
dp[i][s] = Math.max(dp[i][s],
arr[j - 1 ] +
dp[i - 1 ][s - j]);
}
}
}
return dp[N][ 2 * (N - 1 )] - 1 ;
}
public static void main(String[] args)
{
int [] arr = { 1 , 3 , 0 };
System.out.print(maxScore(arr));
}
}
|
Python3
def maxScore(arr):
N = len (arr)
N + = 1
dp = [[ - 100000 for i in range ( 2 * N)]
for i in range (N + 1 )]
dp[ 0 ][ 0 ] = 0
for i in range ( 1 , N + 1 ):
for s in range ( 1 , 2 * (N - 1 ) + 1 ):
j = 1
while j < = N - 1 and j < = s:
dp[i][s] = max (dp[i][s], arr[j - 1 ] +
dp[i - 1 ][s - j])
j + = 1
return dp[N][ 2 * (N - 1 )]
if __name__ = = '__main__' :
arr = [ 1 , 3 , 0 ]
print (maxScore(arr))
|
C#
using System;
class GFG{
static int maxScore( int [] arr)
{
int N = arr.Length;
N++;
int [,] dp = new int [N + 1,
2 * (N -
1) + 1];
dp[0, 0] = 0;
for ( int i = 1; i <= N; i++)
{
for ( int s = 1;
s <= 2 * (N - 1); s++)
{
for ( int j = 1;
j <= N - 1 && j <= s; j++)
{
dp[i, s] = Math.Max(dp[i, s],
arr[j - 1] +
dp[i - 1,
s - j]);
}
}
}
return dp[N, 2 * (N -
1)] - 1;
}
public static void Main(String[] args)
{
int [] arr = {1, 3, 0};
Console.Write(maxScore(arr));
}
}
|
Javascript
<script>
function maxScore(arr)
{
var N = arr.length;
N++;
var dp = Array.from(Array(N+1), ()=> Array(2*N).fill(-10000000));
dp[0][0] = 0;
for ( var i = 1; i <= N; i++) {
for ( var s = 1;
s <= 2 * (N - 1); s++) {
for ( var j = 1; j <= N - 1
&& j <= s;
j++) {
dp[i][s]
= Math.max(dp[i][s],
arr[j - 1]
+ dp[i - 1][s - j]);
}
}
}
return dp[N][2 * (N - 1)];
}
var arr = [1, 3, 0];
document.write( maxScore(arr));
</script>
|
Time Complexity: O(N3)
Auxiliary Space: O(N2)
Efficient Approach : Space optimization
we have eliminated the use of unnecessary rows in the dp array and used only two rows (one for the current iteration and one for the previous iteration) to store the values. We have also replaced the dp[i][s] with dp[curr][s] and dp[i-1][s-j] with dp[prev][s-j] to further reduce memory usage.
Implementation Steps:
- Create a DP vector table of 2 rows to only determine current and previous computations.
- Initialize DP with -100000 because we are finding a maximum value to update DP.
- Now Iterate over subproblems through nested loops and get the computation of current problem from previous and current row of DP.
- At last return answer store in dp[N % 2][2 * (N – 1)].
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int maxScore(vector< int >& arr) {
int N = arr.size();
N++;
vector<vector< int >> dp(2, vector< int >(2 * N, -100000));
dp[0][0] = 0;
for ( int i = 1; i <= N; i++) {
int curr = i % 2, prev = (i - 1) % 2;
for ( int s = 1; s <= 2 * (N - 1); s++) {
dp[curr][s] = -100000;
for ( int j = 1; j <= N - 1 and j <= s; j++) {
dp[curr][s] = max(dp[curr][s], arr[j - 1] + dp[prev][s - j]);
}
}
}
return dp[N % 2][2 * (N - 1)];
}
int main() {
vector< int > arr = { 1, 3, 0 };
cout << maxScore(arr);
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int maxScore(List<Integer> arr) {
int N = arr.size();
N++;
List<List<Integer>> dp = new ArrayList<>();
for ( int i = 0 ; i < 2 ; i++) {
List<Integer> row = new ArrayList<>();
for ( int j = 0 ; j < 2 * N; j++) {
row.add(- 100000 );
}
dp.add(row);
}
dp.get( 0 ).set( 0 , 0 );
for ( int i = 1 ; i <= N; i++) {
int curr = i % 2 , prev = (i - 1 ) % 2 ;
for ( int s = 1 ; s <= 2 * (N - 1 ); s++) {
dp.get(curr).set(s, - 100000 );
for ( int j = 1 ; j <= N - 1 && j <= s; j++) {
dp.get(curr).set(s, Math.max(dp.get(curr).get(s), arr.get(j - 1 ) + dp.get(prev).get(s - j)));
}
}
}
return dp.get(N % 2 ).get( 2 * (N - 1 ));
}
public static void main(String[] args) {
List<Integer> arr = new ArrayList<>(Arrays.asList( 1 , 3 , 0 ));
System.out.println(maxScore(arr));
}
}
|
C#
using System;
public class Program
{
public static int maxScore( int [] arr)
{
int N = arr.Length;
N++;
int [][] dp = new int [2][];
dp[0] = new int [2 * N];
dp[1] = new int [2 * N];
for ( int i = 0; i < 2 * N; i++) {
dp[0][i] = -100000;
dp[1][i] = -100000;
}
dp[0][0] = 0;
for ( int i = 1; i <= N; i++)
{
int curr = i % 2, prev = (i - 1) % 2;
for ( int s = 1; s <= 2 * (N - 1); s++) {
dp[curr][s] = -100000;
for ( int j = 1; j <= N - 1 && j <= s; j++) {
dp[curr][s] = Math.Max(
dp[curr][s],
arr[j - 1] + dp[prev][s - j]);
}
}
}
return dp[N % 2][2 * (N - 1)];
}
public static void Main()
{
int [] arr = { 1, 3, 0 };
Console.WriteLine(maxScore(arr));
}
}
|
Python3
def maxScore(arr):
N = len (arr)
N + = 1
dp = [[ - 100000 ] * ( 2 * N) for i in range ( 2 )]
dp[ 0 ][ 0 ] = 0
for i in range ( 1 , N + 1 ):
curr = i % 2
prev = (i - 1 ) % 2
for s in range ( 1 , 2 * (N - 1 ) + 1 ):
dp[curr][s] = - 100000
for j in range ( 1 , N) :
if j < = s:
dp[curr][s] = max (dp[curr][s], arr[j - 1 ] + dp[prev][s - j])
return dp[N % 2 ][ 2 * (N - 1 )]
arr = [ 1 , 3 , 0 ]
print (maxScore(arr))
|
Javascript
function maxScore(arr) {
let N = arr.length;
N++;
let dp = new Array(2).fill( null ).map(() => new Array(2 * N).fill(-100000));
dp[0][0] = 0;
for (let i = 1; i <= N; i++) {
let curr = i % 2;
let prev = (i - 1) % 2;
for (let s = 1; s <= 2 * (N - 1); s++) {
dp[curr][s] = -100000;
for (let j = 1; j <= N - 1 && j <= s; j++) {
dp[curr][s] = Math.max(dp[curr][s], arr[j - 1] + dp[prev][s - j]);
}
}
}
return dp[N % 2][2 * (N - 1)];
}
let arr = [1, 3, 0];
console.log(maxScore(arr));
|
Time Complexity: O(N*N*N)
Auxiliary Space: O(N) or O(N*2)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...