指出潜在的溢出错误

时间:2015-06-07 11:29:26

标签: c++ algorithm long-integer integer-overflow

这是我对采访问题的解决方案。 link

  

您将获得一个从1到n的n个整数的只读数组。   每个整数只出现一次,除了A出现两次,B出现缺失。   返回A和B.   注意:您的算法应具有线性运行时复杂性。你能不用额外的内存来实现吗?   请注意,在输出A中应该在B. N <= 10 ^ 5

之前

看起来某处存在溢出问题。你能指出这些地方并建议修复。

  typedef long long int unit;

vector<int> Solution::repeatedNumber(const vector<int> &A) {
    unit n = A.size();
    unit sum = n*(n+1)/2;
    unit sumsq = n*(n+1)*(2*n+1)/6;
    unit arrsum = std::accumulate(A.begin(), A.end(), 0);


    unit arrsq = 0;
    for(int item : A) {
        arrsq += (unit)item*item;
    }

    unit c1 = arrsum - sum;

    unit c2 = arrsq - sumsq;

    unit a = (c2/c1 + c1);
    a/=2;

    unit b = (c2/c1 - c1);
    b/=2;

    return {a, b};
}

P.S它必须是溢出问题,因为相同的解决方案适用于Python。

更新 这是问题作者提供的解决方案。有趣的是他如何通过减法来解决总和中的溢出问题。

 class Solution {
public:
    vector<int> repeatedNumber(const vector<int> &V) {
       long long sum = 0;
       long long squareSum = 0;
       long long temp;
       for (int i = 0; i < V.size(); i++) {
           temp = V[i];
           sum += temp;
           sum -= (i + 1);
           squareSum += (temp * temp);
           squareSum -= ((long long)(i + 1) * (long long)(i + 1));
       }
       // sum = A - B
       // squareSum = A^2 - B^2 = (A - B)(A + B)
       // squareSum / sum = A + B
       squareSum /= sum;

       // Now we have A + B and A - B. Lets figure out A and B now. 
       int A = (int) ((sum + squareSum) / 2);
       int B = squareSum - A;

       vector<int> ret;
       ret.push_back(A);
       ret.push_back(B);
       return ret;
    }
};

2 个答案:

答案 0 :(得分:2)

问题在于:

unit arrsum = std::accumulate(A.begin(), A.end(), 0);

您需要使用0LL将值累积为long 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;
}

在没有-727379968的情况下输出LL,并输出正确的结果。

请注意,您还可以使用accumulate来计算平方和:

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

答案 1 :(得分:0)

潜在的溢出问题是:

{ [MongoError: Unable to execute query: error processing query: ns=dev.locations limit=1000 skip=0
Tree: GEONEAR  field=loc maxdist=0.156961 isNearSphere=0
Sort: {}
Proj: {}
planner returned error: unable to find index for $geoNear query]
name: 'MongoError',
message: 'Unable to execute query: error processing query: ns=dev.locations limit=1000 skip=0\nTree: GEONEAR  field=loc maxdist=0.156961 isNearSphere=0\nSort: {}\nProj: {}\n planner returned error: unable to find index for $geoNear query',
'$err': 'Unable to execute query: error processing query: ns=dev.locations limit=1000 skip=0\nTree: GEONEAR  field=loc maxdist=0.156961 isNearSphere=0\nSort: {}\nProj: {}\n planner returned error: unable to find index for $geoNear query',
code: 17007 }

这里最大的n值是10 ^ 5。因此,n *(n + 1)将产生10 ^ 10,然后由于运算符优先级而计算除法。

第二位是

unit sum = n*(n+1)/2;

此处计算的中间值高达10 ^ 15。

在你计算所有数字的平方和的地方还有整数溢出。