我的目标是回答以下问题/查询: 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
我的想法是这样的:
按x的系数按递减顺序对函数进行排序。
按递增顺序对查询进行排序
摆脱并行函数,保留具有最小常数项的函数(例如:如果我有f(x)= 2 * x + 4且g(x)= 2 * x + 2,f (x)永远不会小于g(x),所以我不需要f(x))。
现在我正处于从-inf到某个实数的区间,称之为w1,我知道在这个区间内,线性系数最高的函数是最小的
通过找到最小的x1 s.t找到w1。 f(x1)= g(x1)其中f是我的当前函数,g迭代所有其他具有较小线性系数的函数,w1 = x1
只要我的查询在区间(-inf,w1)中重复:输出当前函数,然后继续下一个查询。
如果我还有需要回答的查询,那么让当前函数为与x = w1处的实际当前函数相交的函数,而不是-inf put w1,重复相同的步骤。
但是,我的实施或想法还不够快。还有什么我没注意到可以加快我的计划吗?
提前谢谢。
答案 0 :(得分:4)
你能解决它们的交叉点,并为域中的每个区间存储最大的函数吗?
编辑 - 详细说明,如果要解决x的任何一对函数,则x表示这两个函数中的一个变得大于另一个函数的值。对于区间中的所有值,最小函数都是可定义的间隔。
以下是3个示例函数的图表。
此图表的间隔(带有相应的最小函数)将为
(-∞, 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);
}