这是算法入门课程中的一个问题:
你有一个n个随机正整数的数组(这个数组没有
需要排序或元素唯一)。提出一个o(n)算法
求元素的最大和,它可以被n整除。
使用动态编程和用余数0,1,2,…,n-1存储最大和,在o(n2)中相对容易找到它。这是一个javascript代码:

function sum_mod_n(a)
{
    var n = a.length;

    var b = new Array(n);
    b.fill(-1);

    for (var i = 0; i < n; i++)
    {
        var u = a[i] % n;
        var c = b.slice();

        for (var j = 0; j < n; j++) if (b[j] > -1)
        {
            var v = (u + j) % n;
            if (b[j] + a[i] > b[v]) c[v] = b[j] + a[i];
        }

        if (c[u] == -1) c[u] = a[i];
        b = c;
    }

    return b[0];
}

对于相邻元素,在o(n)中也很容易找到它,存储mod n的部分和。另一个示例:
function cont_mod_n(a)
{
    var n = a.length;

    var b = new Array(n);
    b.fill(-1);

    b[0] = 0;

    var m = 0, s = 0;

    for (var i = 0; i < n; i++)
    {
        s += a[i];
        var u = s % n;
        if (b[u] == -1) b[u] = s;
        else if (s - b[u] > m) m = s - b[u];
    }

    return m;
}

但一般情况下O(N)如何?任何建议都将不胜感激!我认为这和线性代数有关,但我不确定具体是什么。
编辑:这实际上可以在o(n logn)中完成吗?

最佳答案

因为你没有指定什么是随机的(均匀的?如果是,在什么时间间隔?)唯一的一般解是任意数组的解,我认为没有比o(n2)更好的解了。这是python中的动态编程算法:

def sum_div(positive_integers):
    n = len(positive_integers)
    # initialise the dynamic programming state
    # the index runs on all possible reminders mod n
    # the DP values keep track of the maximum sum you can have for that reminder
    DP = [0] * n
    for positive_integer in positive_integers:
        for remainder, max_sum in list(enumerate(DP)):
            max_sum_next = max_sum + positive_integer
            remainder_next = max_sum_next % n
            if max_sum_next > DP[remainder_next]:
                DP[remainder_next] = max_sum_next
    return DP[0]

如果数组中的值有一个上限(例如n),则可能可以得出一个更快的解决方案。

关于algorithm - 被n整除的总和,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35530263/

10-12 18:19