C++ 指出潜在的溢出错误

C++ 指出潜在的溢出错误,c++,algorithm,long-integer,integer-overflow,C++,Algorithm,Long Integer,Integer Overflow,以下是我对面试问题的解决方案。 您将获得一个只读数组,其中包含从1到n的n个整数。 每个整数只出现一次,除了出现两次的A和丢失的B。 返回A和B。 注意:您的算法应该具有线性运行时复杂性。你能在不使用额外内存的情况下实现它吗? 请注意,在您的输出中,A应在B之前。N潜在的溢出问题是: unit sum = n*(n+1)/2; 此处的最大n值为10^5。因此,n*(n+1)将产生10^10,然后根据运算符优先级计算除法 第二名是 unit sum = n*(n+1)(2*n+1)/6; 此

以下是我对面试问题的解决方案。

您将获得一个只读数组,其中包含从1到n的n个整数。 每个整数只出现一次,除了出现两次的A和丢失的B。 返回A和B。 注意:您的算法应该具有线性运行时复杂性。你能在不使用额外内存的情况下实现它吗?
请注意,在您的输出中,A应在B之前。N潜在的溢出问题是:

unit sum = n*(n+1)/2;
此处的最大n值为10^5。因此,n*(n+1)将产生10^10,然后根据运算符优先级计算除法

第二名是

unit sum = n*(n+1)(2*n+1)/6;
此处计算的中间值最多为10^15

在计算所有数字的平方和时,也存在整数溢出。

问题在于:

unit arrsum = std::accumulate(A.begin(), A.end(), 0);
您需要使用
0LL
使其将值累积为
long

演示问题的代码:

int main()
{
    vector<int> A;
    for (int i = 0; i < 1000000; ++i)
        A.push_back(1000000);

    long long arrsum = accumulate(A.begin(), A.end(), 0LL);
    cout << arrsum;

    return 0;
}

你能删除这些评论吗?它们不会导致问题,但会降低代码的可读性。另外,我想知道“无额外内存”的含义有多严格,因为您正在使用额外内存。@tobi303,它意味着使用的内存应该是O(1)(不应该取决于输入长度)。我认为它应该是b=(c1-c2/c1)/2。您的解决方案输出-b而不是b@OphirGvirtzer,我相信就公式而言是正确的。它正确地计算结果。-------------------------------------
单元
被类型化为
long
,因此这些表达式不应该溢出。这3个表达式中不应该有溢出。长long int定义为“不小于long”,至少64位。“64符号位可以保持10 ^ 18.9,而(n+1)*(n+1)(2n+1)是最坏情况下的10 ^ 16。这是C++如何在腿部拍摄无辜程序员的可怕例子。我希望编译器至少产生一个警告。@OphirGvirtzer-为什么?我用C++很少,但它立刻对我说他在<代码> int <代码> >中使用<代码>累积>代码>。除了
int
,它还能返回什么?生成初始值
0LL
可能不那么直观,但将初始数组更改为
long
是直观的,也会起作用。@lVlad您在这个示例中是对的。但是同样的情况发生在数组长的时候,如果不使用0LL,我认为这很可怕(VC++不警告)。这确实很奇怪。只有少数人能理解模板类型推断的规则。。。
unit arrsum = std::accumulate(A.begin(), A.end(), 0);
int main()
{
    vector<int> A;
    for (int i = 0; i < 1000000; ++i)
        A.push_back(1000000);

    long long arrsum = accumulate(A.begin(), A.end(), 0LL);
    cout << arrsum;

    return 0;
}
unit arrsq = accumulate(A.begin(), A.end(), 0LL, 
                             [](unit x, unit y) { return x + y*y; });