找到丢失的卡(更快的解决方案

时间:2016-06-02 08:04:43

标签: python algorithm optimization

我们给出了N(3 <= N <= 50000)卡,其中唯一的数字从1到N. 我们丢失了3张牌,我们的目标是找到它们。

输入:第一行包含卡数N. 第二行包含3个数字:我们拥有的所有左卡的总和,它们的正方形的总和以及它们的立方体的总和。

输出:任意顺序的3张丢失卡数。

在这里我尝试了:我找到了相同的3张丢失的卡片,然后检查可能的数字,直到其中三张满足我们的总和。

有更快的解决方案吗?我必须在Python中传递2秒的时间限制,最大N = 50000。

N = int(input())
lst = list(range(1, N+1))
s_rest, s2_rest, s3_rest = list(map(int, input().split()))

s = sum(lst)
s2 = sum([x**2 for x in lst])
s3 = sum([x**3 for x in lst])
# sums of 3 lost numbers
s_lost = s - s_rest
s2_lost = s2 - s2_rest
s3_lost = s3 - s3_rest


def find_numbers():
    """Find first appropriate option"""
    for num1 in range(s_lost):
        for num2 in range(s_lost):
            for num3 in range(s_lost):
                if (num1 + num2 + num3 == s_lost) and (num1**2 + num2**2 + num3**2 == s2_lost)\
                        and (num1**3 + num2**3 + num3**3 == s3_lost):
                    return (num1, num2, num3)

answer = find_numbers()
print(answer[0], answer[1], answer[2])

实施例

输入

4

1 1 1

输出:

2 3 4

输入

5

6 26 126

输出:

2 3 4

5 个答案:

答案 0 :(得分:2)

如果你的未知数字是x,y,z,那么你有一个三个方程的系统

x + y + z = a  //your s_lost
x^2 + y^2 + z^2 = b  //your s2_lost
x^3 + y^3 + z^3 = c  //your s3_lost

虽然这个系统的直接解决方案似乎过于复杂,但我们可以修复一个未知的并解决更简单的系统。例如,检查z的所有可能值并解决x和y的系统

 for z in range(s_lost):
 ....

现在让我们来看看新系统:

 x + y  = a - z = aa
 x^2 + y^2 = b - z^2 = bb
 substitute
 x = aa - y
 (aa - y)^2 + y^2 = bb
 2 * y^2 - 2 * y * aa - bb + aa^2 = 0
 solve this quadratic equation for y
 D = 4 * aa^2 - 8 * (aa^2 - bb) = 8 * bb -4 * aa^2
 y(1,2) = (2*aa +- Sqrt(D)) / 4

因此,对于每个z值,找到:
- 解是否给出y的整数值 - 然后得到x
- 然后检查立方体和方程式是否为真。

使用这种方法,您将获得线性复杂度O(N)与立方复杂度O(N ^ 3)的解。

P.S。如果对方程系统确实存在相当简单的数学解,则它具有复杂度O(1))

答案 1 :(得分:1)

这可以通过数学方法简化。你有3个方程,有3个未知数。

sum(1+2+..+N) - x1 - x2 - x3 = a  
sum(1^2+2^2+..+N^2) - x1^2 - x2^2 - x3^3 = b  
sum(1^3+2^3+..+N^3) - x1^3 - x2^3 - x3^3 = c

显然sum(1..N)1/2 *N(N+1),而sum(1^2+2^2+3^2+..+N^2)1/6 *N*(N+1)*(2N+1)sum(1^3+2^3+..+N^3)可以写成1/4 *N^2 *(N+1)^2。以下是wolframalpha输出:∑k∑k^2∑k^3

此时只剩下解决给定的方程组(3个具有3个未知数的方法是完全可解的)并实现这一点。您只需找到一个解决方案,使其更容易。运行时间为O(1)。

答案 2 :(得分:0)

肯定存在更快的方法!

对于N = 50,000,你的蛮力功能必须弥补

N * N * N = 125,000,000,000,000  

迭代,所以这不是一个选项。

此外,您应该检查num1 == num2等以避免重复的数字(问题没有明确说明,但我明白'我们丢失了3张卡'意味着您需要找到三个不同< / em>满足给定条件的数字。)

答案 3 :(得分:0)

您可以对列表进行排序,并找到401 {"err_code":401,"err_msg":"Unauthorized"} 对的对。对于每个这样的对,都缺少a[i+1] =/= a[i]+1个数字。这将为您提供O(n log n)运行时间。

答案 4 :(得分:0)

我可以给你一个想法,

sum1 = 1+2+3...n

sum2 = 1^2+2^2+3^2...n

p, q, r是连续输入的三个数字。

我们需要搜索a, b, c。迭代for c = 1 to N.

对于每次迭代,

x = sum1 - (p+c)

y = sum2 - (q+c*c)

所以a+b = xa^2+b^2 = y

a^2+b^2 = (a+b)^2 - 2ab起,您可以从等式2ab中找到a^2+b^2 = y

a+b已知且ab已知,通过一些小数学计算,您可以找到ab是否存在解(它形成二次方程) )。如果存在,请打印解决方案并中断迭代。

这是一个O(N)解决方案。