我刚刚在准备考试时遇到了一个考试问题,我被困住了。问题是:
设计一个算法,给定一组正整数 X,确定方程 x 5 + xy - y 2 = y 3是否具有 x 和 y 都属于 X 的解。
不涉及编程,只是算法设计。有人可以分享他们的想法吗?
暴力是不可接受的
我刚刚在准备考试时遇到了一个考试问题,我被困住了。问题是:
设计一个算法,给定一组正整数 X,确定方程 x 5 + xy - y 2 = y 3是否具有 x 和 y 都属于 X 的解。
不涉及编程,只是算法设计。有人可以分享他们的想法吗?
暴力是不可接受的
伪代码:
result = false
foreach (x in X) {
foreach (y in X) {
if (x^5 + x*y - y^2 == y^3) result = true
}
}
是否比预期的更复杂?如果是这样,可以像这样利用高阶项x^5
:
Sort X as a list from least to greatest.
result = false
foreach (y in X) {
v = y*y*(y+1)
foreach (x in X) {
x2 = x*x
u = x2*x2 + x*y - v
if (u == 0) {
result = true
goto [DONE]
}
if (u > 0) goto [NEXT]
}
[NEXT]
}
[DONE]
对于(真的!)大量输入,您可以:
x
,所以方程变成了 的三次方程y
,那么公式是适用的。然而,这个公式可能需要很长时间,为了避免可能的精度问题,您可以插入答案来检查它。然后对排序列表(O(logn))进行二进制搜索。这将渐近 O(nlogn),但常数因素是可怕的,并且被大哦很好地隐藏了(好吧,如果你正在回答问题,而不是编写程序)。当然,如果允许散列(这通常是面试的情况,但不一定是考试),这可能是 O(n)。
求解 y 作为 x 的函数:http ://www.wolframalpha.com/input/?i=x%5E5%2B+xy+-+y%5E2+-+y%5E3
y(x) := INSERT_EQUATION_HERE
any((y in setX) for y in y(x) for x in setX)
这需要 O(|X|),即线性时间。
或者,如果您没有使用具有any
函数或列表操作的语言,那么您的解决方案必须更加冗长:
for x in setX:
possibleYs = solveForY(x)
for y in possibleYs:
if y in setX:
return SOLUTION:(x,y)
return NO_SOLUTION
您实际上不必像我上面展示的那样求解 2D 多项式。相反,您可以考虑集合中的每个 x;这修复了 x 并为您提供了 y 中的多项式。然后,您在恒定时间内求解该多项式。例如,如果 x=0,我们会找到 y^2==y^3 的 3 个解;如果 x=1,我们会找到 2-y^2==y^3 的 3 个解决方案,如果 x=-0.52,我们会等等。解决方案是http://en.wikipedia.org/wiki/ Cubic_function#General_formula_of_roots
问题的更一般版本:
如果您考虑任意多项式,请注意此方法只能在以下情况下提供 O(1) 效率:min(max_x_degree, max_y_degree)<5。这是因为,正如伽罗瓦理论所证明的那样,唯一具有某些封闭形式解的多项式是 4 次或更小的多项式。而在这个问题中,我们可以把度数最高的变量变成一个常数。
这并不是说在 min(max_x_degree, max_y_degree)<5 的情况下,不能通过其他方法获得 O(1) 效率。
如果增加变量的数量,事情也会变得更有趣。
如果集合 X 不是很大,那么简单的蛮力算法可以通过构造 2D 矩阵来工作。