【问题标题】:Refactoring Dynamic Approach for Optimal Binary Search Tree重构最优二叉搜索树的动态方法
【发布时间】:2015-05-13 08:57:36
【问题描述】:

总的来说,我对动态编程和 CS 的概念非常陌生。我通过阅读在线发布的讲座、观看视频和解决发布在 GeeksforGeeks 和 Hacker Rank 等网站上的问题来自学。

问题

给定输入

3 25 30 5

where 3 =  #of keys

25 = frequency of key 1

30 = frequency of key 2

5  = frequency of key 3

如果每个键都以优化的方式排列,我将打印最低成本。这是一个最优的二叉搜索树问题,我在 geeks 上找到了一个类似的解决方案。

#include <stdio.h>
#include <limits.h>

// 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[] = {0,1,2};
    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;
}

然而,在这个解决方案中,他们也接受了“键”的输入,但他们似乎对最终答案没有影响,因为他们不应该这样做。重要的是每个键被搜索多少次的频率。

为了简单起见和理解这种动态方法,我想知道如何修改这个解决方案,以便它以上面显示的格式接受输入并打印结果。

【问题讨论】:

  • 我不明白问题的描述。 “以优化的方式安排”到底是什么意思?
  • 最优二叉搜索树问题是关于构建一个二叉搜索树,根据给定的每个键的搜索频率最小化搜索的平均成本。当频率都相同时,任何最小深度(即平衡)树都可以,但是当频率不同时,最优树将倾向于在根附近聚集更频繁搜索的键,结果可能是不平衡的.在这种特殊情况下,实际的树不是输出,只是搜索它的平均成本的度量。
  • @Codor John 发布了一个很好的描述。如果我不清楚,我很抱歉。显然谷歌使用类似的东西来存储他们的搜索关键字。显然它一定要复杂得多,但这是基本思想。
  • 谢谢,这很有见地!
  • 请注意,顺便说一句,“每个键被搜索多少次的频率很重要”(强调添加)是不正确的。由于您只想考虑 search 树,因此键/频率的顺序很重要,即使特定的键值不重要。

标签: c algorithm dynamic-programming


【解决方案1】:

您提供的函数确实有一个keys 参数,但它没有使用它。您可以完全删除它。


编辑:特别是,由于函数 optimalSearchTree() 根本不使用其 keys 参数,删除该参数只需要更改函数签名 (.. .

int optimalSearchTree(int freq[], int n)

...) 以及对该函数的一次调用。但是,由于您不需要此特定练习的密钥,因此您也可以将它们从主程序中完全删除,以提供给您:

int main()
{
    int freq[] = {25, 30, 5};
    int n = sizeof(freq)/sizeof(freq[0]);
    printf("Cost of Optimal BST is %d ", optimalSearchTree(freq, n));
    return 0;
}

(将您指定的频率值替换为原始代码中的频率值)


但是,该函数确实假设频率是按键值递增的顺序给出的。它至少需要相对键顺序来完成它的工作,因为否则你不能构造一个 search 树。如果您对键值未知的想法感到不舒服,您可以将代码解释为使用freq[] 数组中的索引作为键值的别名。这是有效的,因为上述假设的结果是 x -> keys[x] 是从整数 0 ... n - 1 到任何值的 1:1 顺序保留 映射实际的键是。

如果函数不能假设频率最初是按按键递增的顺序给出的,那么它可以首先使用按键将频率排序为该顺序,然后像现在一样继续。

【讨论】:

  • 我也是这么认为的,但是当我删除此行时,我得到了不同的答案。 sum(freq, i, j);
  • 感谢您的回答,我想知道您是否可以发布重构的代码。对于像我这样的新手来说,只有所需的代码更容易理解。
  • 是的,如果您从成本计算中删除术语 sum(freq, i, j),您会得到不同的答案。这与频率有关(参数freq),而不是键。
  • 我已经编辑了我的答案,以准确显示删除 keys 参数会是什么样子。
  • 谢谢,只是一个问题,它不也调用 sum 实用函数来将所有键相加吗?不影响最终结果吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
相关资源
最近更新 更多