我在Adobe采访中被问到这个问题:
我们有一个整数数组,按升序排序。我们还有3个整数A
,B
和C
。我们需要为数组中的每个元素A*x*x + B*x + C
应用x
并返回相应的排序数组。
给出了示例I:
Input array = -1 0 1 2 3 4
A = -1, B = 2, C = -1`
将公式应用于每个元素的结果= -4 -1 0 -1 -4 -9
所以期望的结果= -9 -4 -4 -1 -1 0
(已排序)
我最好的解决方案是应用公式并对其进行排序,从而得到O(nlogn)
解决方案。我无法做得更好。
任何改进指南都是有帮助的。
答案 0 :(得分:19)
给出的等式为parabolic。因此,将它应用于有序数组的结果将导致一个数组具有最大/最小值,其子数组的左右排序。
在您的情况下,最大值为0
,左侧的子数组[-4 -1]
按升序排序,右侧的子数组[-1 -4 -9]
按降序排序。
您需要做的就是 合并这些排序后的数组 ,这是时间线性的。
所以算法是:
答案 1 :(得分:5)
您可以在O(n)
中执行此操作。找到
2 * A * x + B = 0
这样
x_min = -B / 2 * A.
然后,遍历数组,直到找到最接近x_min
的整数。这是O(n)
。从此处开始,根据|x_min - left|
是小于还是大于|x_min - right|
,从该元素的左侧或右侧连续选取。返回在结果顺序中在这些点处评估多项式的值。这是O(n)
。
这假设A
为正。您可以类似地处理否定A
的情况。
示例:
input array = -1 0 1 2 3 4 A = -1, B = 2, C = -1
此处,最大值出现在x_max = -2 / 2 * -1 = 1
。从输入数组中,最接近的值是1
,即第三个元素。然后,我们根据它们与1
的距离,按以下顺序连续选取元素。
1, 0, 2, -1, 3, 4
然后,因为A
是否定的,我们必须以相反的顺序运行它们
4, 3, -1, 2, 0, 1
并评估它们上的多项式
-9, -4, -4, -1, -1, 0
完成。
请注意,我们正在利用抛物线的特殊属性。也就是说,对于x
小于x_extreme
且A
为正,将多项式应用于此类x
是x
的递减函数。如果x
大于x_extreme
且A
为正,则将多项式应用于此类x
是x
的递增函数。 (如果A
为负数,则类似推理适用。)因此,将数组分为两部分,x
小于x_extreme
且x
大于x_extreme
。然后将多项式应用于这两个部分,最后得到两个已排序的数组。现在将merge排序应用于这些已排序的数组。请注意,上面的描述实际上是合并排序。
答案 2 :(得分:1)
解决方案是O(N)
并且不需要执行任何微积分,尽管它有助于理解曲线的形状。
上面的答案是做最直观的事情并解决方程式以找到最小值或最大值,然后拆分列表。
计算一阶导数有一个优点,但不需要实际这样做,我们也不需要在此时找到最大或最小点。
只要知道它可以向一个方向移动然后向另一个方向移动但是不会多次改变方向。
我们将从每一端开始并从两侧迭代,直到我们合并到中间的某个地方。在我们做任何其他事情之前,我们需要检查每一端的方向,我们将通过比较最后两个元素来做。所以我们看看一端是向上移动而另一端向下移动。
如果我们有N
个元素,请假设我们有数据X[0]
和X[N-1]
,因此请计算f(X[0])
和f(X[N-1])
以及f(X[1])
和{{ 1}}。如果f(X[N-2])
和f(X[0]) < f(X[1])
实际上我们所有的数据都是最大值/最小值的一侧,因此已经排序。如果比较是在另一个方向,则相同。 (一个方向可能需要反向)。
否则只需从两端执行合并,因此f(X[N-1]) > f(X[N-2])
和f(X[0])
是其子范围的最大值或最小值(我们从早期的比较中得知)并创建合并列表,无论哪个是适当的方向。
申请数据:
f(X[N-1])
-1 0 1 2 3 4
A = -1, B = 2, C = -1`
f = [ -4, -1, 0, -1, -4, -9 ]
和-4 < -1
所以我们确实跨越了这一点,我们在每一端都有最低点。
-9 < -4
答案 3 :(得分:0)
你可以认识到将二次方应用于数据的结果几乎是分类的(如上面的答案所述,或者通过认识到n次多项式的导数是连续的,n-1度,并且在大多数零。)
因此,如果您的库中有一个排序例程,它可以通过几乎排序的数据(例如记住这一点的mergesort)做一些巧妙的事情,您可以将数据抛出并预期线性性能。在网上搜索Which sort algorithm works best on mostly sorted data? 它指向http://svn.python.org/projects/python/trunk/Objects/listsort.txt。