# Optimal Binary Search Tree | DP-24

Given a sorted array keys[0.. n-1] of search keys and an array freq[0.. n-1] of frequency counts, where freq[i] is the number of searches to keys[i]. Construct a binary search tree of all keys such that the total cost of all the searches is as small as possible.

Let us first define the cost of a BST. The cost of a BST node is level of that node multiplied by its frequency. Level of root is 1.

Examples:

```Input:  keys[] = {10, 12}, freq[] = {34, 50}
There can be following two possible BSTs
10                       12
/
12                 10
I                     II
Frequency of searches of 10 and 12 are 34 and 50 respectively.
The cost of tree I is 34*1 + 50*2 = 134
The cost of tree II is 50*1 + 34*2 = 118

Input:  keys[] = {10, 12, 20}, freq[] = {34, 8, 50}
There can be following possible BSTs
10                12                 20         10              20
/                  /                         /
12          10     20           12               20         10
/                 /
20                        10                12             12
I               II             III             IV             V
Among all possible BSTs, cost of the fifth BST is minimum.
Cost of the fifth BST is 1*50 + 2*34 + 3*8 = 142
```

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

1) Optimal Substructure:
The optimal cost for freq[i..j] can be recursively calculated using following formula. We need to calculate optCost(0, n-1) to find the result.

The idea of above formula is simple, we one by one try all nodes as root (r varies from i to j in second term). When we make rth node as root, we recursively calculate optimal cost from i to r-1 and r+1 to j.
We add sum of frequencies from i to j (see first term in the above formula), this is added because every search will go through root and one comparison will be done for every search.

2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure mentioned above.

## C++

// A naive recursive implementation of
// optimal binary search tree problem
#include
using namespace std;

// A utility function to get sum of
// array elements freq[i] to freq[j]
int sum(int freq[], int i, int j);

// A recursive function to calculate
// cost of optimal binary search tree
int optCost(int freq[], int i, int j)
{
// Base cases
if (j < i) // no elements in this subarray return 0; if (j == i) // one element in this subarray return freq[i]; // Get sum of freq[i], freq[i+1], ... freq[j] int fsum = sum(freq, i, j); // Initialize minimum value int min = INT_MAX; // One by one consider all elements // as root and recursively find cost // of the BST, compare the cost with // min and update min if needed for (int r = i; r <= j; ++r) { int cost = optCost(freq, i, r - 1) + optCost(freq, r + 1, j); if (cost < min) min = cost; } // Return minimum value return min + fsum; } // The main function that calculates // minimum cost of a Binary Search Tree. // It mainly uses optCost() to find // the optimal cost. int optimalSearchTree(int keys[], int freq[], int n) { // Here array keys[] is assumed to be // sorted in increasing order. If keys[] // is not sorted, then add code to sort // keys, and rearrange freq[] accordingly. return optCost(freq, 0, n - 1); } // A utility function to get sum of // array elements freq[i] to freq[j] int sum(int freq[], int i, int j) { int s = 0; for (int k = i; k <= j; k++) s += freq[k]; return s; } // Driver Code int main() { int keys[] = {10, 12, 20}; int freq[] = {34, 8, 50}; int n = sizeof(keys) / sizeof(keys); cout << "Cost of Optimal BST is " << optimalSearchTree(keys, freq, n); return 0; } // This is code is contributed // by rathbhupendra [tabby title="C"]

 `// A naive recursive implementation of optimal binary  ` `// search tree problem ` `#include ` `#include ` ` `  `// A utility function to get sum of array elements  ` `// freq[i] to freq[j] ` `int` `sum(``int` `freq[], ``int` `i, ``int` `j); ` ` `  `// A recursive function to calculate cost of optimal  ` `// binary search tree ` `int` `optCost(``int` `freq[], ``int` `i, ``int` `j) ` `{ ` `   ``// Base cases ` `   ``if` `(j < i)      ``// no elements in this subarray ` `     ``return` `0; ` `   ``if` `(j == i)     ``// one element in this subarray ` `     ``return` `freq[i]; ` ` `  `   ``// Get sum of freq[i], freq[i+1], ... freq[j] ` `   ``int` `fsum = sum(freq, i, j); ` ` `  `   ``// Initialize minimum value ` `   ``int` `min = INT_MAX; ` ` `  `   ``// One by one consider all elements as root and ` `   ``// recursively find cost of the BST, compare the ` `   ``// cost with min and update min if needed ` `   ``for` `(``int` `r = i; r <= j; ++r) ` `   ``{ ` `       ``int` `cost = optCost(freq, i, r-1) +  ` `                  ``optCost(freq, r+1, j); ` `       ``if` `(cost < min) ` `          ``min = cost; ` `   ``} ` ` `  `   ``// Return minimum value ` `   ``return` `min + fsum; ` `} ` ` `  `// The main function that calculates minimum cost of ` `// a Binary Search Tree. It mainly uses optCost() to  ` `// find the optimal cost. ` `int` `optimalSearchTree(``int` `keys[], ``int` `freq[], ``int` `n) ` `{ ` `     ``// Here array keys[] is assumed to be sorted in  ` `     ``// increasing order. If keys[] is not sorted, then  ` `     ``// add code to sort keys, and rearrange freq[]  ` `     ``// accordingly. ` `     ``return` `optCost(freq, 0, n-1); ` `} ` ` `  `// A utility function to get sum of array elements  ` `// freq[i] to freq[j] ` `int` `sum(``int` `freq[], ``int` `i, ``int` `j) ` `{ ` `    ``int` `s = 0; ` `    ``for` `(``int` `k = i; k <=j; k++) ` `       ``s += freq[k]; ` `    ``return` `s; ` `} ` ` `  `// Driver program to test above functions ` `int` `main() ` `{ ` `    ``int` `keys[] = {10, 12, 20}; ` `    ``int` `freq[] = {34, 8, 50}; ` `    ``int` `n = ``sizeof``(keys)/``sizeof``(keys); ` `    ``printf``(``"Cost of Optimal BST is %d "``,  ` `               ``optimalSearchTree(keys, freq, n)); ` `    ``return` `0; ` `} `

## Java

 `// A naive recursive implementation of optimal binary  ` `// search tree problem ` `public` `class` `GFG  ` `{ ` `    ``// A recursive function to calculate cost of ` `        ``// optimal binary search tree ` `    ``static` `int` `optCost(``int` `freq[], ``int` `i, ``int` `j) ` `    ``{ ` `       ``// Base cases ` `       ``if` `(j < i)      ``// no elements in this subarray ` `         ``return` `0``; ` `       ``if` `(j == i)     ``// one element in this subarray ` `         ``return` `freq[i]; ` `      `  `       ``// Get sum of freq[i], freq[i+1], ... freq[j] ` `       ``int` `fsum = sum(freq, i, j); ` `      `  `       ``// Initialize minimum value ` `       ``int` `min = Integer.MAX_VALUE; ` `      `  `       ``// One by one consider all elements as root and  ` `           ``// recursively find cost of the BST, compare the  ` `           ``// cost with min and update min if needed ` `       ``for` `(``int` `r = i; r <= j; ++r) ` `       ``{ ` `           ``int` `cost = optCost(freq, i, r-``1``) +  ` `                          ``optCost(freq, r+``1``, j); ` `           ``if` `(cost < min) ` `              ``min = cost; ` `       ``} ` `      `  `       ``// Return minimum value ` `       ``return` `min + fsum; ` `    ``} ` `     `  `    ``// The main function that calculates minimum cost of ` `        ``// a Binary Search Tree. It mainly uses optCost() to ` `        ``// find the optimal cost. ` `    ``static` `int` `optimalSearchTree(``int` `keys[], ``int` `freq[], ``int` `n) ` `    ``{ ` `         ``// Here array keys[] is assumed to be sorted in  ` `             ``// increasing order. If keys[] is not sorted, then ` `             ``// add code to sort keys, and rearrange freq[]  ` `             ``// accordingly. ` `         ``return` `optCost(freq, ``0``, n-``1``); ` `    ``} ` `     `  `    ``// A utility function to get sum of array elements  ` `        ``// freq[i] to freq[j] ` `    ``static` `int` `sum(``int` `freq[], ``int` `i, ``int` `j) ` `    ``{ ` `        ``int` `s = ``0``; ` `        ``for` `(``int` `k = i; k <=j; k++) ` `           ``s += freq[k]; ` `        ``return` `s; ` `    ``} ` `     `  `    ``// Driver code ` `    ``public` `static` `void` `main(String[] args) { ` `        ``int` `keys[] = {``10``, ``12``, ``20``}; ` `        ``int` `freq[] = {``34``, ``8``, ``50``}; ` `        ``int` `n = keys.length; ` `        ``System.out.println(``"Cost of Optimal BST is "` `+ ` `                         ``optimalSearchTree(keys, freq, n)); ` `    ``} ` `} ` `// This code is contributed by Sumit Ghosh `

## Python3

 `# A naive recursive implementation of  ` `# optimal binary search tree problem  ` ` `  `# A recursive function to calculate  ` `# cost of optimal binary search tree  ` `def` `optCost(freq, i, j): ` `     `  `    ``# Base cases  ` `    ``if` `j < i:     ``# no elements in this subarray  ` `        ``return` `0` `    ``if` `j ``=``=` `i:     ``# one element in this subarray  ` `        ``return` `freq[i]  ` `     `  `    ``# Get sum of freq[i], freq[i+1], ... freq[j]  ` `    ``fsum ``=` `Sum``(freq, i, j)  ` `     `  `    ``# Initialize minimum value  ` `    ``Min` `=` `999999999999` `     `  `    ``# One by one consider all elements as  ` `    ``# root and recursively find cost of  ` `    ``# the BST, compare the cost with min ` `    ``# and update min if needed  ` `    ``for` `r ``in` `range``(i, j ``+` `1``): ` `        ``cost ``=` `(optCost(freq, i, r ``-` `1``) ``+` `                ``optCost(freq, r ``+` `1``, j))  ` `        ``if` `cost < ``Min``:  ` `            ``Min` `=` `cost ` `     `  `    ``# Return minimum value  ` `    ``return` `Min` `+` `fsum ` ` `  `# The main function that calculates minimum  ` `# cost of a Binary Search Tree. It mainly  ` `# uses optCost() to find the optimal cost.  ` `def` `optimalSearchTree(keys, freq, n): ` `     `  `    ``# Here array keys[] is assumed to be  ` `    ``# sorted in increasing order. If keys[]  ` `    ``# is not sorted, then add code to sort   ` `    ``# keys, and rearrange freq[] accordingly.  ` `    ``return` `optCost(freq, ``0``, n ``-` `1``) ` ` `  `# A utility function to get sum of ` `# array elements freq[i] to freq[j]  ` `def` `Sum``(freq, i, j): ` `    ``s ``=` `0` `    ``for` `k ``in` `range``(i, j ``+` `1``): ` `        ``s ``+``=` `freq[k]  ` `    ``return` `s ` ` `  `# Driver Code ` `if` `__name__ ``=``=` `'__main__'``: ` `    ``keys ``=` `[``10``, ``12``, ``20``]  ` `    ``freq ``=` `[``34``, ``8``, ``50``]  ` `    ``n ``=` `len``(keys)  ` `    ``print``(``"Cost of Optimal BST is"``,  ` `           ``optimalSearchTree(keys, freq, n)) ` `     `  `# This code is contributed by PranchalK `

## C#

 `// A naive recursive implementation of optimal binary  ` `// search tree problem ` `using` `System; ` ` `  `class` `GFG ` `{ ` `    ``// A recursive function to calculate cost of ` `    ``// optimal binary search tree ` `    ``static` `int` `optCost(``int` `[]freq, ``int` `i, ``int` `j) ` `    ``{ ` `         `  `    ``// Base cases ` `    ``// no elements in this subarray ` `    ``if` `(j < i)      ` `        ``return` `0; ` `     `  `    ``// one element in this subarray     ` `    ``if` `(j == i)      ` `        ``return` `freq[i]; ` `     `  `    ``// Get sum of freq[i], freq[i+1], ... freq[j] ` `    ``int` `fsum = sum(freq, i, j); ` `     `  `    ``// Initialize minimum value ` `    ``int` `min = ``int``.MaxValue; ` `     `  `    ``// One by one consider all elements as root and  ` `    ``// recursively find cost of the BST, compare the  ` `    ``// cost with min and update min if needed ` `    ``for` `(``int` `r = i; r <= j; ++r) ` `    ``{ ` `        ``int` `cost = optCost(freq, i, r-1) +  ` `                        ``optCost(freq, r+1, j); ` `        ``if` `(cost < min) ` `            ``min = cost; ` `    ``} ` `     `  `    ``// Return minimum value ` `    ``return` `min + fsum; ` `    ``} ` `     `  `    ``// The main function that calculates minimum cost of ` `    ``// a Binary Search Tree. It mainly uses optCost() to ` `    ``// find the optimal cost. ` `    ``static` `int` `optimalSearchTree(``int` `[]keys, ``int` `[]freq, ``int` `n) ` `    ``{ ` `        ``// Here array keys[] is assumed to be sorted in  ` `        ``// increasing order. If keys[] is not sorted, then ` `        ``// add code to sort keys, and rearrange freq[]  ` `        ``// accordingly. ` `        ``return` `optCost(freq, 0, n-1); ` `    ``} ` `     `  `    ``// A utility function to get sum of array elements  ` `    ``// freq[i] to freq[j] ` `    ``static` `int` `sum(``int` `[]freq, ``int` `i, ``int` `j) ` `    ``{ ` `        ``int` `s = 0; ` `        ``for` `(``int` `k = i; k <=j; k++) ` `        ``s += freq[k]; ` `        ``return` `s; ` `    ``} ` `     `  `    ``// Driver code ` `    ``public` `static` `void` `Main()  ` `    ``{ ` `        ``int` `[]keys = {10, 12, 20}; ` `        ``int` `[]freq = {34, 8, 50}; ` `        ``int` `n = keys.Length; ` `        ``Console.Write(``"Cost of Optimal BST is "` `+ ` `                        ``optimalSearchTree(keys, freq, n)); ` `    ``} ` `} ` ` `  `// This code is contributed by Sam007 `

Output:

`Cost of Optimal BST is 142`

Time complexity of the above naive recursive approach is exponential. It should be noted that the above function computes the same subproblems again and again. We can see many subproblems being repeated in the following recursion tree for freq[1..4]. Since same suproblems are called again, this problem has Overlapping Subprolems property. So optimal BST problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided by constructing a temporary array cost[][] in bottom up manner.

Dynamic Programming Solution
Following is C/C++ implementation for optimal BST problem using Dynamic Programming. We use an auxiliary array cost[n][n] to store the solutions of subproblems. cost[n-1] will hold the final result. The challenge in implementation is, all diagonal values must be filled first, then the values which lie on the line just above the diagonal. In other words, we must first fill all cost[i][i] values, then all cost[i][i+1] values, then all cost[i][i+2] values. So how to fill the 2D array in such manner> The idea used in the implementation is same as Matrix Chain Multiplication problem, we use a variable ‘L’ for chain length and increment ‘L’, one by one. We calculate column number ‘j’ using the values of ‘i’ and ‘L’.

## C/C++

 `// Dynamic Programming code for Optimal Binary Search  ` `// Tree Problem ` `#include ` `#include ` ` `  `// A utility function to get sum of array elements  ` `// freq[i] to freq[j] ` `int` `sum(``int` `freq[], ``int` `i, ``int` `j); ` ` `  `/* A Dynamic Programming based function that calculates ` `  ``minimum cost of a Binary Search Tree. */` `int` `optimalSearchTree(``int` `keys[], ``int` `freq[], ``int` `n) ` `{ ` `    ``/* Create an auxiliary 2D matrix to store results  ` `      ``of subproblems */` `    ``int` `cost[n][n]; ` ` `  `    ``/* cost[i][j] = Optimal cost of binary search tree ` `       ``that can be  formed from keys[i] to keys[j]. ` `       ``cost[n-1] will store the resultant cost */` ` `  `    ``// For a single key, cost is equal to frequency of the key ` `    ``for` `(``int` `i = 0; i < n; i++) ` `        ``cost[i][i] = freq[i]; ` ` `  `    ``// Now we need to consider chains of length 2, 3, ... . ` `    ``// L is chain length. ` `    ``for` `(``int` `L=2; L<=n; L++) ` `    ``{ ` `        ``// i is row number in cost[][] ` `        ``for` `(``int` `i=0; i<=n-L+1; i++) ` `        ``{ ` `            ``// Get column number j from row number i and  ` `            ``// chain length L ` `            ``int` `j = i+L-1; ` `            ``cost[i][j] = INT_MAX; ` ` `  `            ``// Try making all keys in interval keys[i..j] as root ` `            ``for` `(``int` `r=i; r<=j; r++) ` `            ``{ ` `               ``// c = cost when keys[r] becomes root of this subtree ` `               ``int` `c = ((r > i)? cost[i][r-1]:0) +  ` `                       ``((r < j)? cost[r+1][j]:0) +  ` `                       ``sum(freq, i, j); ` `               ``if` `(c < cost[i][j]) ` `                  ``cost[i][j] = c; ` `            ``} ` `        ``} ` `    ``} ` `    ``return` `cost[n-1]; ` `} ` ` `  `// A utility function to get sum of array elements  ` `// freq[i] to freq[j] ` `int` `sum(``int` `freq[], ``int` `i, ``int` `j) ` `{ ` `    ``int` `s = 0; ` `    ``for` `(``int` `k = i; k <=j; k++) ` `       ``s += freq[k]; ` `    ``return` `s; ` `} ` ` `  `// Driver program to test above functions ` `int` `main() ` `{ ` `    ``int` `keys[] = {10, 12, 20}; ` `    ``int` `freq[] = {34, 8, 50}; ` `    ``int` `n = ``sizeof``(keys)/``sizeof``(keys); ` `    ``printf``(``"Cost of Optimal BST is %d "``,  ` `                 ``optimalSearchTree(keys, freq, n)); ` `    ``return` `0; ` `} `

## Java

 `// Dynamic Programming Java code for Optimal Binary Search ` `// Tree Problem ` `public` `class` `Optimal_BST2 { ` `     `  `    ``/* A Dynamic Programming based function that calculates ` `        ``minimum cost of a Binary Search Tree.  */` `    ``static` `int` `optimalSearchTree(``int` `keys[], ``int` `freq[], ``int` `n) { ` ` `  `        ``/* Create an auxiliary 2D matrix to store results of  ` `           ``subproblems */` `        ``int` `cost[][] = ``new` `int``[n + ``1``][n + ``1``]; ` ` `  `        ``/* cost[i][j] = Optimal cost of binary search tree that  ` `           ``can be formed from keys[i] to keys[j]. cost[n-1]  ` `           ``will store the resultant cost */` ` `  `        ``// For a single key, cost is equal to frequency of the key ` `        ``for` `(``int` `i = ``0``; i < n; i++) ` `            ``cost[i][i] = freq[i]; ` ` `  `        ``// Now we need to consider chains of length 2, 3, ... . ` `        ``// L is chain length. ` `        ``for` `(``int` `L = ``2``; L <= n; L++) { ` ` `  `            ``// i is row number in cost[][] ` `            ``for` `(``int` `i = ``0``; i <= n - L + ``1``; i++) { ` ` `  `                ``// Get column number j from row number i and  ` `                ``// chain length L ` `                ``int` `j = i + L - ``1``; ` `                ``cost[i][j] = Integer.MAX_VALUE; ` ` `  `                ``// Try making all keys in interval keys[i..j] as root ` `                ``for` `(``int` `r = i; r <= j; r++) { ` ` `  `                    ``// c = cost when keys[r] becomes root of this subtree ` `                    ``int` `c = ((r > i) ? cost[i][r - ``1``] : ``0``) ` `                            ``+ ((r < j) ? cost[r + ``1``][j] : ``0``) + sum(freq, i, j); ` `                    ``if` `(c < cost[i][j]) ` `                        ``cost[i][j] = c; ` `                ``} ` `            ``} ` `        ``} ` `        ``return` `cost[``0``][n - ``1``]; ` `    ``} ` ` `  `    ``// A utility function to get sum of array elements  ` `    ``// freq[i] to freq[j] ` `    ``static` `int` `sum(``int` `freq[], ``int` `i, ``int` `j) { ` `        ``int` `s = ``0``; ` `        ``for` `(``int` `k = i; k <= j; k++) { ` `            ``if` `(k >= freq.length) ` `                ``continue``; ` `            ``s += freq[k]; ` `        ``} ` `        ``return` `s; ` `    ``} ` ` `  `    ``public` `static` `void` `main(String[] args) { ` `         `  `        ``int` `keys[] = { ``10``, ``12``, ``20` `}; ` `        ``int` `freq[] = { ``34``, ``8``, ``50` `}; ` `        ``int` `n = keys.length; ` `        ``System.out.println(``"Cost of Optimal BST is "` `                ``+ optimalSearchTree(keys, freq, n)); ` `    ``} ` ` `  `} ` `//This code is contributed by Sumit Ghosh `

## Python3

 `# Dynamic Programming code for Optimal Binary Search  ` `# Tree Problem  ` ` `  `INT_MAX ``=` `2147483647` ` `  `""" A Dynamic Programming based function that ` `calculates minimum cost of a Binary Search Tree. """` `def` `optimalSearchTree(keys, freq, n): ` ` `  `    ``""" Create an auxiliary 2D matrix to store ` `        ``results of subproblems """` `    ``cost ``=` `[[``0` `for` `x ``in` `range``(n)]  ` `               ``for` `y ``in` `range``(n)] ` ` `  `    ``""" cost[i][j] = Optimal cost of binary search  ` `    ``tree that can be formed from keys[i] to keys[j].  ` `    ``cost[n-1] will store the resultant cost """` ` `  `    ``# For a single key, cost is equal to ` `    ``# frequency of the key  ` `    ``for` `i ``in` `range``(n): ` `        ``cost[i][i] ``=` `freq[i]  ` ` `  `    ``# Now we need to consider chains of  ` `    ``# length 2, 3, ... . L is chain length.  ` `    ``for` `L ``in` `range``(``2``, n ``+` `1``): ` `     `  `        ``# i is row number in cost  ` `        ``for` `i ``in` `range``(n ``-` `L ``+` `2``): ` `             `  `            ``# Get column number j from row number  ` `            ``# i and chain length L  ` `            ``j ``=` `i ``+` `L ``-` `1` `            ``if` `i >``=` `n ``or` `j >``=` `n: ` `                ``break` `            ``cost[i][j] ``=` `INT_MAX ` `             `  `            ``# Try making all keys in interval  ` `            ``# keys[i..j] as root  ` `            ``for` `r ``in` `range``(i, j ``+` `1``): ` `                 `  `                ``# c = cost when keys[r] becomes root  ` `                ``# of this subtree ` `                ``c ``=` `0` `                ``if` `(r > i): ` `                    ``c ``+``=` `cost[i][r ``-` `1``] ` `                ``if` `(r < j): ` `                    ``c ``+``=` `cost[r ``+` `1``][j] ` `                ``c ``+``=` `sum``(freq, i, j)  ` `                ``if` `(c < cost[i][j]): ` `                    ``cost[i][j] ``=` `c ` `    ``return` `cost[``0``][n ``-` `1``]  ` ` `  ` `  `# A utility function to get sum of  ` `# array elements freq[i] to freq[j]  ` `def` `sum``(freq, i, j): ` ` `  `    ``s ``=` `0` `    ``for` `k ``in` `range``(i, j ``+` `1``): ` `        ``s ``+``=` `freq[k]  ` `    ``return` `s  ` `     `  `# Driver Code ` `if` `__name__ ``=``=` `'__main__'``: ` `    ``keys ``=` `[``10``, ``12``, ``20``] ` `    ``freq ``=` `[``34``, ``8``, ``50``] ` `    ``n ``=` `len``(keys) ` `    ``print``(``"Cost of Optimal BST is"``, ` `           ``optimalSearchTree(keys, freq, n)) ` `     `  `# This code is contributed by SHUBHAMSINGH10 `

## C#

 `// Dynamic Programming C# code for Optimal Binary Search ` `// Tree Problem ` `using` `System; ` ` `  `class` `GFG ` `{ ` `    ``/* A Dynamic Programming based function that calculates ` `    ``minimum cost of a Binary Search Tree. */` `    ``static` `int` `optimalSearchTree(``int` `[]keys, ``int` `[]freq, ``int` `n) { ` ` `  `        ``/* Create an auxiliary 2D matrix to store results of  ` `        ``subproblems */` `        ``int` `[,]cost = ``new` `int``[n + 1,n + 1]; ` ` `  `        ``/* cost[i][j] = Optimal cost of binary search tree that  ` `        ``can be formed from keys[i] to keys[j]. cost[n-1]  ` `        ``will store the resultant cost */` ` `  `        ``// For a single key, cost is equal to frequency of the key ` `        ``for` `(``int` `i = 0; i < n; i++) ` `            ``cost[i,i] = freq[i]; ` ` `  `        ``// Now we need to consider chains of length 2, 3, ... . ` `        ``// L is chain length. ` `        ``for` `(``int` `L = 2; L <= n; L++) { ` ` `  `            ``// i is row number in cost[][] ` `            ``for` `(``int` `i = 0; i <= n - L + 1; i++) { ` ` `  `                ``// Get column number j from row number i and  ` `                ``// chain length L ` `                ``int` `j = i + L - 1; ` `                ``cost[i,j] = ``int``.MaxValue; ` ` `  `                ``// Try making all keys in interval keys[i..j] as root ` `                ``for` `(``int` `r = i; r <= j; r++) { ` ` `  `                    ``// c = cost when keys[r] becomes root of this subtree ` `                    ``int` `c = ((r > i) ? cost[i,r - 1] : 0) ` `                            ``+ ((r < j) ? cost[r + 1,j] : 0) + sum(freq, i, j); ` `                    ``if` `(c < cost[i,j]) ` `                        ``cost[i,j] = c; ` `                ``} ` `            ``} ` `        ``} ` `        ``return` `cost[0,n - 1]; ` `    ``} ` ` `  `    ``// A utility function to get sum of array elements  ` `    ``// freq[i] to freq[j] ` `    ``static` `int` `sum(``int` `[]freq, ``int` `i, ``int` `j) { ` `        ``int` `s = 0; ` `        ``for` `(``int` `k = i; k <= j; k++) { ` `            ``if` `(k >= freq.Length) ` `                ``continue``; ` `            ``s += freq[k]; ` `        ``} ` `        ``return` `s; ` `    ``} ` ` `  `    ``public` `static` `void` `Main() { ` `         `  `        ``int` `[]keys = { 10, 12, 20 }; ` `        ``int` `[]freq = { 34, 8, 50 }; ` `        ``int` `n = keys.Length; ` `        ``Console.Write(``"Cost of Optimal BST is "` `                ``+ optimalSearchTree(keys, freq, n)); ` `    ``} ` `} ` `// This code is contributed by Sam007 `

Output:

`Cost of Optimal BST is 142`

Notes
1) The time complexity of the above solution is O(n^4). The time complexity can be easily reduced to O(n^3) by pre-calculating sum of frequencies instead of calling sum() again and again.

2) In the above solutions, we have computed optimal cost only. The solutions can be easily modified to store the structure of BSTs also. We can create another auxiliary array of size n to store the structure of tree. All we need to do is, store the chosen ‘r’ in the innermost loop.