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

Equilibrium index of an array of large numbers, how to prevent overflow?

本文关键字:何防止 溢出 指数 数组      更新时间:2023-10-16

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

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

问题:
我发现的所有解决方案(有效)都是基于这样一个事实,即给定所有元素的总和和一个部分的当前运行总和,我们可以通过扣除剩余部分元素的总和来获得。我不认为解决方案是正确的,因为如果我们为大向量提供MAX_INT元素,元素的总和将导致溢出。
如何解决溢出问题?
建议解决方案的参考,所有这些都无法解决溢出问题(我只指C++实现,据我所知,在Java中存在解决它的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>);
}

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

问题很简单:任何计算机的内存都是有限的。我们可以表示的数字总是有一些有限的限制。任意精度整数类型可以增加对数字的限制,远远大于大多数使用常规使用的数字,无论限制是什么,总会有更大的数字无法表示(至少在不更改为其他表示形式的情况下 - 但是如果我们要对任意数字的单位位置进行精确, 对于我们在表示巨大数字方面的聪明程度,有明显的限制)。

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

我想可能有某种方法可以计算出这个问题的答案,而不涉及实际对数字求和 - 但至少乍一看,这个想法对我来说似乎不是很有希望。问题的陈述专门涉及计算总和。虽然您当然可以进行各种阴谋诡计来防止求和看起来像求和,但事实是问题的基本陈述涉及求和,这往往表明不涉及求和的解决方案可能很难找到。

是的,这是可能的。请注意,如果data[0] < data[len - 1],则data[1]应属于"左"部分;同样,如果data[0] > data[len-1]那么data[len-2]属于"正确"部分。这种观察允许归纳证明以下算法的正确性:

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没有溢出的可能性。可能需要对有符号值进行一些修改。