Optimal binary search tree | Practice | GeeksforGeeks

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.

Example 1:
Input:
n = 2
keys = {10, 12}
freq = {34, 50}
Output: 118
Explaination:
There can be following two possible BSTs 
        10                       12
          \                     / 
           12                 10
                              
The cost of tree I is 34*1 + 50*2 = 134
The cost of tree II is 50*1 + 34*2 = 118 

Example 2:

Input:
N = 3
keys = {10, 12, 20}
freq = {34, 8, 50}
Output: 142
Explaination: There can be many possible BSTs
     20
    /
   10  
    \
     12  
     
Among all possible BSTs, 
cost of this BST is minimum.  
Cost of this BST is 1*50 + 2*34 + 3*8 = 142

Your Task:
You don't need to read input or print anything. Your task is to complete the function optimalSearchTree() which takes the array keys[], freq[] and their size n as input parameters and returns the total cost of all the searches is as small as possible.

Expected Time Complexity: O(n3)
Expected Auxiliary Space: O(n2)

Constraints:
1 ≤ N ≤ 100
+2
sangamchoudhary72 months ago
It should in extreme hard category 
+1
geminicode2 months ago
Must have been a hard problem !! here's the python solution.
def optimalSearchTree(self, keys, freq, n):
        # code here
        dp = [[0 for i in range(n)] for j in range(n)]
        for g in range(n):
            for i,j in zip(range(n-g),range(g,n)):
                #print(i,j)
                if g == 0:
                    dp[i][j] = freq[i]
                if g == 1:
                    dp[i][j] = min(2*freq[i] + freq[j], 2*freq[j] + freq[i])
                else:
                    mini = 99999999999999
                    sumi = 0
                    for x in range(i,j+1):
                        sumi+=freq[x]
                    for k in range(i,j+1):
                        left = 0 if k == i else dp[i][k-1]
                        right = 0 if k == j else dp[k+1][j]
                        if left + right + sumi < mini:
                            mini = left + right + sumi
                    dp[i][j] = mini
                        
        #print(dp)
        return dp[0][n-1]
-2
gargishant2 months ago
LeetCode POTD discussion:
https://youtu.be/d5Vl5BH0RXc
+3
subha_nik2 months ago
Solution using Recursion + Memoization:
Time taken: 0.1/3.5✅
Time Complexity: O(n3)
Space Complexity: O(n2) auxiliary + O(n) stack space
Code:
const int INF = 1e9;

class Solution{
    public:
    int solve(int i, int j, int freq[], vector<vector<int>>& dp) {
        if(i > j) return 0;
        if(dp[i][j] != INF) return dp[i][j];
        
        int sum = 0;
        for(int k=i; k<=j; k++) sum += freq[k];
        
        for(int k=i; k<=j; k++)
            dp[i][j] = min(dp[i][j], sum+solve(i,k-1,freq,dp)+solve(k+1,j,freq,dp));
        
        return dp[i][j];
    }
    
    int optimalSearchTree(int keys[], int freq[], int n) {
        vector<vector<int>> dp(n, vector<int>(n,INF));
        
        for(int i=0; i<n; i++)
            dp[i][i] = freq[i];
        
        return solve(0,n-1,freq,dp);
    }
};
0
saroj80096854602 months ago
Bold italic semi blocysemi collme
+1
saranyamaity20002 months ago
how people are getting AC on a wrong test cases !!!
EDIT : here one testcase is wrong , they haven't provided the keys as sorted :) sad lyf! GFG what you are doing! 
+3
youcando2 months ago
MCM C++ VARIATION:
explanation:
the most imp part is why we are doing freq sum??
because for first tree we have summed the tree and for second one we will added again and for third one we will add again so we can say the (level*freq) rule follows here
 
ex. assume your optimal  bst is :
a
   \
     b
        \
           c
and frqs are a',b' and c' respectively
now i am making my root node ‘a’ and thinks about left and right subtree ans :
a→a' 
   \
     b→b'
        \
           c→c'
step 1 recur: ans=a'+b'+c'+(left +right)
here left=0;
right will be  calculated by recur
 
and when recur to root b then ans of b
 
b'+c'+c'
 
here b' +c' is sum and c' is returned by base case(i==j) see in code
 
so final=a'+b'+c'+(b'+c'+c')=a'+2*b'+3*c'
 
which is our level*freq rule for calculation of ans or we can say cost
 
 
 
------------------------------------------------------------------------------
code:
 int dp[101][101];   int sum(int i,int j,int frq[]){       int s=0;       for(int k=i;k<=j;k++){           s+=frq[k];       }       return s;   }   int mcm(int i,int j,int freq[]){             if(j<i) return 0;       if(i==j) return freq[i];       if(dp[i][j]!=-1) return dp[i][j];       int sum1=sum(i,j,freq);       int ans=INT_MAX;       for(int k=i;k<=j;k++){           ans=min(ans,mcm(i,k-1,freq)+mcm(k+1,j,freq));       }       return dp[i][j]=ans+sum1;   }   int optimalSearchTree(int keys[], int freq[], int n)   {           memset(dp,-1,sizeof dp);      return mcm(0,n-1,freq);   }
+2
pritamkr2122 months ago
OK BRO IF WANT TO LEARN SOME I AM GIVING THE LINK OF VIDEO https://youtu.be/HnslzEs8dbY PLEASE WATCH IT .ITS WORTH IT,TOU WILL NEVER REGRET IT 
class Solution
{
    static int optimalSearchTree(int keys[], int freq[], int n)
    {
        int[]pre=new int[n];
        pre[0]=freq[0];
        for(int i=1;i<n;i++)pre[i]=(pre[i-1]+freq[i]);
        int[][]dp=new int[n][n];
        for(int g=0;g<n;g++){
            for(int i=0,j=g;j<n;j++,i++){
                if(g==0)dp[i][j]=freq[i];
                else if(g==1){
                    int f1=dp[i][j-1];
                    int f2=dp[i+1][j];
                    dp[i][j]=Math.min(f1+2*f2,2*f1+f2);
                }
                else{
                    int min=Integer.MAX_VALUE;
                    int fs=pre[j]-(i==0?0:pre[i-1]);
                    for(int k=i;k<=j;k++){
                        int left=k==i?0:dp[i][k-1];
                        int right=k==j?0:dp[k+1][j];
                        if(left+right+fs<min)min=left+right+fs;
                    }
                    dp[i][j]=min;
                }
            }
        }
        return dp[0][n-1];
    }
}
+1
atulrajj112 months ago
//PrerequisiteGap strategy+prefix sum+Basics of 2D dp int optimalSearchTree(int keys[], int freq[], int n)   {       int sum=0;       vector<int> pre(n+1);       pre[0]=0;       for(int i=1;i<=n;i++)       {           pre[i]=pre[i-1]+freq[i-1];       }     int dp[n][n];   //   memset(dp,0,sizeof(dp));     for(int g=0;g<n;g++)     {         for(int i=0,j=g;j<n;i++,j++)         {             if(g==0)             {                 dp[i][j]=freq[i];             }             else if(g==1)             {                 dp[i][j]=min(freq[i]*1+freq[j]*2,freq[i]*2+freq[j]*1);             }             else{                 int ans=INT_MAX;                 for(int k=i;k<=j;k++)                 {                     int left,right;                     if(k==i)                            left=0;                     else left=dp[i][k-1];                                          if(k==j)                     {                         right=0;                     }                     else right=dp[k+1][j];                     ans=min(ans,left+right);                 }                 dp[i][j]=ans+pre[j+1]-pre[i];             }         }     }     return dp[0][n-1];   }
0
samantaavijit20002 months ago
JAVA SOLUTION 
class Solution{   static int optimalSearchTree(int key[], int freq[], int n)   {       int store[][][]=new int [n][n][n+1];       for(int i=0;i<n;i++){         for(int j=0;j<n;j++){             for(int k=0;k<=n;k++)               store[i][j][k]=-1;         }     }  return dp(0,n-1,1,key,freq,store);   }      public static  int dp(int i,int j,int level,int key[],int freq[],int store[][][]){    if(i==j){        store[i][j][level]=freq[i]*level;        return(store[i][j][level]);    }    if(i>j)      return(0);        if(store[i][j][level]!=-1)     return(store[i][j][level]);        int min=Integer.MAX_VALUE;    for(int r=i;r<=j;r++){        int v1=dp(i,r-1,level+1,key,freq,store);        int v2=dp(r+1,j,level+1,key,freq,store);        int v3=freq[r]*level;        int total=v1+v2+v3;        min=Math.min(total,min);    }    store[i][j][level]=min;    return(min);}} 
We strongly recommend solving this problem on your own before viewing its editorial. Do you still
                    want to view the editorial?
 Login to access your submissions. 

Problem


Contest

Reset the IDE using the second button on the top right corner.
Avoid using static/global variables in your code as your code is tested against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases does not guarantee the correctness of code. On submission, your code is tested against multiple test cases consisting of all possible corner cases and stress constraints.
You can access the hints to get an idea about what is expected of you as well as the final solution code.
You can view the solutions submitted by other users from the submission tab.