📜  最佳二叉搜索树| DP-24

📅  最后修改于: 2021-05-24 21:21:37             🧑  作者: Mango

给定一个排序后的数组键[0 … N-1]的搜索键和阵列频率[0 … N-1]的频率计数,其中频率[i]为搜索到的密钥[I]的数量。构造一个包含所有关键字的二叉搜索树,以使所有搜索的总成本尽可能小。

让我们首先定义BST的成本。 BST节点的成本是该节点的级别乘以其频率。根级别为1。

例子:

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

1)最佳子结构:
可以使用以下公式递归计算freq [i..j]的最佳成本。
 optcost\left ( i, \right j) = \sum_{k=i}^{j} freq \begin{bmatrix}k\end{bmatrix} + min_{r=i}^{j}\begin{bmatrix} optcost(i, r-1) + optcost(r+1, j) \end{bmatrix}

我们需要计算optCost(0,n-1)才能找到结果。

上面公式的想法很简单,我们一个接一个地尝试所有节点作为根(第二项中r从i到j变化)。当我们将第r个节点设为根时,我们递归地计算从i到r-1和r + 1到j的最优成本。
我们将i到j的频率总和相加(请参阅上式中的第一项),这是因为每次搜索都将通过根,并且每次搜索都将进行一次比较。

2)重叠子问题
以下是简单地遵循上述递归结构的递归实现。

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[0]); 
    cout << "Cost of Optimal BST is " 
         << optimalSearchTree(keys, freq, n); 
    return 0; 
} 
  
// This is code is contributed
// by rathbhupendra


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[0]);
    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


C++
// Dynamic Programming code for 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 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[0][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[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[0]); 
    cout << "Cost of Optimal BST is " << optimalSearchTree(keys, freq, n); 
    return 0; 
} 
  
// This code is contributed by rathbhupendra


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[0][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[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[0]);
    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[0][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[0][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[0][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


输出:

Cost of Optimal BST is 142

上述幼稚递归方法的时间复杂度是指数的。应该注意的是,上述函数一次又一次地计算相同的子问题。我们可以看到在下面的递归树中,对于freq [1..4]重复了许多子问题。

由于再次调用了相同的问题,因此此问题具有“重叠子问题”属性。因此,最佳BST问题具有动态编程问题的两个属性(请参阅此内容)。像其他典型的动态规划(DP)问题一样,可以通过自下而上构造临时数组cost [] []来避免相同子问题的重新计算。

动态编程解决方案
以下是使用动态编程实现最佳BST问题的C / C++实现。我们使用辅助数组cost [n] [n]存储子问题的解。 cost [0] [n-1]将保留最终结果。实现中的挑战是,必须首先填充所有对角线值,然后填充对角线正上方的线上的值。换句话说,我们必须首先填充所有cost [i] [i]值,然后填充所有cost [i] [i + 1]值,然后填充所有cost [i] [i + 2]值。因此,如何以这种方式填充2D数组>实现中使用的思想与矩阵链乘法问题相同,我们对链长使用变量’L’,并逐个递增’L’。我们使用“ i”和“ L”的值计算列号“ j”。

C++

// Dynamic Programming code for 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 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[0][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[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[0]); 
    cout << "Cost of Optimal BST is " << optimalSearchTree(keys, freq, n); 
    return 0; 
} 
  
// This code is contributed by rathbhupendra

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[0][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[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[0]);
    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[0][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[0][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[0][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

输出:

Cost of Optimal BST is 142

笔记
1)上述解决方案的时间复杂度为O(n ^ 4)。通过预先计算频率之和而不是一次又一次地调用sum(),可以很容易地将时间复杂度降低到O(n ^ 3)。

2)在上述解决方案中,我们仅计算了最佳成本。可以轻松修改解决方案以存储BST的结构。我们可以创建另一个大小为n的辅助数组来存储树的结构。我们要做的就是将所选的“ r”存储在最里面的循环中。