找到最小的功能

时间:2012-05-20 22:36:25

标签: algorithm optimization geometry

好的,这是交易。我有一堆线性函数,a * x + b。

我的目标是回答以下问题/查询: x = q时的最小函数是什么?

例如:如果我有函数f(x)= 3 * x + 2,g(x)= 5 * x - 6且h(x)= 2 * x + 1,我将回答例如:

  • 对于x = 4,函数h

  • 对于x = 2,函数g

  • 对于x = 1,函数g

我的想法是这样的:

  1. 按x的系数按递减顺序对函数进行排序。

  2. 按递增顺序对查询进行排序

  3. 摆脱并行函数,保留具有最小常数项的函数(例如:如果我有f(x)= 2 * x + 4且g(x)= 2 * x + 2,f (x)永远不会小于g(x),所以我不需要f(x))。

  4. 现在我正处于从-inf到某个实数的区间,称之为w1,我知道在这个区间内,线性系数最高的函数是最小的

  5. 通过找到最小的x1 s.t找到w1。 f(x1)= g(x1)其中f是我的当前函数,g迭代所有其他具有较小线性系数的函数,w1 = x1

  6. 只要我的查询在区间(-inf,w1)中重复:输出当前函数,然后继续下一个查询。

  7. 如果我还有需要回答的查询,那么让当前函数为与x = w1处的实际当前函数相交的函数,而不是-inf put w1,重复相同的步骤。

  8. 但是,我的实施或想法还不够快。还有什么我没注意到可以加快我的计划吗?

    提前谢谢。

2 个答案:

答案 0 :(得分:4)

你能解决它们的交叉点,并为域中的每个区间存储最大的函数吗?

编辑 - 详细说明,如果要解决x的任何一对函数,则x表示这两个函数中的一个变得大于另一个函数的值。对于区间中的所有值,最小函数都是可定义的间隔。

以下是3个示例函数的图表。 enter image description here

此图表的间隔(带有相应的最小函数)将为

(-∞, 7/3]     => 5x - 6
(7/3, ∞]      => 2x + 1

现在,在运行时,而不是“x = q时的最小函数是什么”,您只需执行“q属于什么时间间隔”

而且,如果我没有弄错的话,如果你有N个线性函数,那么你最多只能存储 N-1个间隔。并且,如果您真的有很多要分析的功能,可以使用专门的数据结构来存储和搜索间隔。

答案 1 :(得分:2)

如果我理解正确,您的解决方案是对所有功能进行一些预处理,以便x的域被分成范围,并且在每个这样的范围内,您都知道什么是最小功能。< / p>

实际上有两个阶段:“准备”和“查询”(在给出特定x的情况下给出结果)。

你的瓶颈是什么?

当然,为了使“查询”阶段更快,你应该用一种排序数组来组织范围,这样你就可以通过中值搜索(或类似)找到包含给定x的范围。对数时间。如果这是你所做的,但仍然不够快 - 考虑代码级优化,因为从算法的角度来看,这似乎是最佳的解决方案。

如果您的瓶颈是“准备”阶段 - 这里有优化的机会。据我所知,你会找到所有函数对的交叉点(在摆脱并行函数之后)。这不是必要的。

请考虑以下事项。首先,按系数对所有函数进行排序(较高的系数在开头)。摆脱并行功能。接下来构建范围数组,同时迭代函数。

由于当前函数具有最低系数(在已经分析过的系数中) - 当x变为无穷大时,当前函数将是最小函数。因此它的范围应该从某个x0到无穷大。找到x0。从数组中取最后一个范围(属于先前处理的函数),找到x0 - 该函数与当前函数的交集。前一个范围缩小到x0。如果该范围变为无效(范围开始大于x0) - 意味着该功能完全被遮挡。在这种情况下 - 删除该范围,并重复该过程。

为了使事情更清楚,我会写一个伪代码:

rangeArr是一对F,X的数组,而F是函数描述,X是函数范围的开头。函数范围的结束被认为是下一个范围的开始,最后一个函数范围的结尾是+无穷大。

for each F sorted by coefficient
{
    double x0;

    while (true)
    {
        if (rangeArr is empty)
        {
            x0 = -inf;
            break;
        }

        FPrev = rangeArr.back().F;
        xPrev = rangeArr.back().X;

        x0 = IntersectionOf(F, FPrev);

        if (x0 > xPrev)
            break;

        rangeArr.DeleteLastRange();
    }

    rangeArr.InsertRange(F, x0);
}