一个大数组的均衡指数,如何防止溢出?

时间:2015-02-04 05:33:03

标签: c++ algorithm vector

问题陈述:
数组的平衡指数是数组的索引,因此较低索引处的元素总和等于较高索引处元素的总和。
例如,在{-7,1,5,2,-4,3,0}中,3是均衡指数,因为:     -7 + 1 + 5 = -4 + 3 + 0

编写一个函数,给定一个int的向量,返回其平衡指数(如果有的话)。假设矢量可能很长。

问题:
我发现的所有解决方案(高效)都基于这样的事实:给定所有元素的总和和一部分的当前运行总和,我们可以通过扣除剩余部分的元素来获得。 我不认为解决方案是正确的,因为如果我们提供带有MAX_INT元素的大向量,则元素之和将导致溢出。
如何解决溢出问题?
对建议的解决方案的参考,所有这些都无法解决溢出问题 (我只是指Java中的C ++实现,据我所知,存在解决它的BigInteger类) http://blog.codility.com/2011/03/solutions-for-task-equi.html
补充材料:

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

template <typename T>
std::vector<size_t> equilibrium(T first, T last)
{
    typedef typename std::iterator_traits<T>::value_type value_t;

    value_t left  = 0;
    value_t right = std::accumulate(first, last, value_t(0));
    std::vector<size_t> result;

    for (size_t index = 0; first != last; ++first, ++index)
    {
        right -= *first;
        if (left == right)
        {
            result.push_back(index);
        }
        left += *first;
    }
    return result;
}

template <typename T>
void print(const T& value)
{
    std::cout << value << "\n";
}

int main() 
{
    const int data[] = { -7, 1, 5, 2, -4, 3, 0 };

    std::vector<size_t> indices(equilibrium(data, data + 7));

    std::for_each(indices.begin(), indices.end(), print<size_t>);
}

2 个答案:

答案 0 :(得分:1)

简短的回答是,最终它不能完全治愈/解决,除非你限制输入的数量/数量 - 甚至不是像Java的BigInt(或C ++的等价物,如gmp,NTL等) 。)

问题很简单:任何计算机中的内存都是有限的。我们可以代表的数字总会有一些限制。任意精度整数类型都可以将数量限制增加到远远超过大多数使用工作的数量,无论限制可能是什么,总会有大得多的数字可以'表示(至少不改变一些其他表示 - 但如果我们要对任意数字的单位放置精确度,那么我们在表示庞大数字方面的聪明程度就有明显的限制。)

对于链接问题中给出的条件,C和C ++中的long long类型就足够了。如果我们想用C ++解决方案将限制增加到一些荒谬的大小,那就非常简单了。虽然它们不是C ++实现的必需部分,但是有许多可用于C ++的任意精度整数库。

我认为可以某种方式来计算这个问题的答案,而这个问题并不涉及到实际数字的总和 - 但至少乍一看,这个想法似乎不太有希望对我来说。该问题的陈述特别是关于计算总和。虽然你当然可以进行各种诡计以保持的总和,如求和,事实是问题的基本陈述涉及总和,这往往表明不涉及总和的解决方案可能很难找到。

答案 1 :(得分:0)

是的,这是可能的。请注意,如果data[0] < data[len - 1],那么data[1]将属于&#34; left&#34;部分;同样,如果data[0] > data[len-1]data[len-2]属于&#34;权利&#34;部分。该观察结果允许对以下算法的正确性进行归纳证明:

left_weight = 0; right_weight = 0
left_index = 0; right_index = 0

while left_index < right_index
    if left_weight < right_weight
        left_weight += data[left_index++];
    else
        right_weight += data[--right_index]

仍然存在积累,但通过跟踪不平衡以及哪一方较重的布尔指标很容易处理:

while left_index < right_index
    if heavier_side == right
        weight = data[left_index++]
    else
        weight = data[--right_index]

    if weight < imbalance
        imbalance = imbalance - weight
    else
        heavier_side = !heavier_side
        imbalance = weight - imbalance

至少对于无符号data,不存在溢出的可能性。签名值可能需要一些修改。