找到子模数M的和的最大值

时间:2016-06-08 11:14:01

标签: arrays dynamic-programming

问题是 - 给你一个大小为N的数组和另一个整数M.你的目标是找到模数为M的子阵列之和的最大值。

If array is {3 3 9 9 5} and M is {7}

可能的子阵列

{3},{3},{9}.{9}.{5}
{3,3},{3,9},{9,9},{9,5}
{3,3,9},{3,9,9},{9,9,5}
{3,3,9,9},{3,9,9,5},{3,3,9,9,5}

其中模数7的最大可能总和为6.子阵列{3,3}具有最大总和。

我遇到了解决方案,但无法理解逻辑

static void solve(long M, long[] array){
    TreeSet<Long> sumSet = new TreeSet<Long>();
    long best = 0;
    long sum = 0;

    for(int i = 0; i < array.length; i++){

        sum = (sum + array[i]) % M;
        Long up = sumSet.higher(sum);
        if(up == null){
            best = Math.max(best,sum);
        } else {
            best = Math.max(best, M - up + sum);
        }
        sumSet.add(sum);
    }

    System.out.println(best);
}

该行意味着什么

 best = Math.max(best, M - up + sum);

1 个答案:

答案 0 :(得分:1)

在模运算中,将除数添加到结果中并没有什么区别。例如,-1 (mod N)N-1相同。 在您的算法中,M - up + sumup减去sum,因为它总是为负数,所以添加M以使结果为正。

算法正在做什么?

  • 使用变量sum
  • 迭代数组并保持运行总和
  • 继续将正在运行的sum存储到TreeSet。我们的想法是能够在O(log N)中提取总和。 sum - (any number from sumSet)是子数组的总和。如果结果为负,则加起来M给出子数组的正和。
  • sum中提取大于sumSet的最小整数。为什么?可能的最大总和是最小的负数。可能的最大模数总和为M - 1。它是在sum - up等于-1时获得的。
  • 如果没有此前的总和,请将当前sumbest进行比较。
  • 否则,请将sum - up + Mbest进行比较。

复杂性:O(n log n)