Java 关于协调性解决方案的问题';s MinMaxDivision,它使用二进制搜索来解决它

Java 关于协调性解决方案的问题';s MinMaxDivision,它使用二进制搜索来解决它,java,algorithm,binary-search,Java,Algorithm,Binary Search,基于在线解决方案,我几乎找到了解决Codibility问题的方法,但解决方案中有一个细节我正在努力确认 问题如下: 任务描述 给定整数K,M和非空数组a 由N个整数组成。数组中的每个元素都不是更大的 比M 您应该将此数组划分为K个连续元素块。 块的大小是介于0和N之间的任意整数 数组应该属于某个块 从X到Y的块总和等于A[X]+A[X+1]+…+A[Y]。 空块的和等于0 大和是任何块的最大和 例如,给定整数K=3、M=5和这样的数组 即: 例如,可以将阵列划分为以下块: [2, 1, 5, 1

基于在线解决方案,我几乎找到了解决Codibility问题的方法,但解决方案中有一个细节我正在努力确认

问题如下:

任务描述

给定整数K,M和非空数组a 由N个整数组成。数组中的每个元素都不是更大的 比M

您应该将此数组划分为K个连续元素块。 块的大小是介于0和N之间的任意整数 数组应该属于某个块

从X到Y的块总和等于A[X]+A[X+1]+…+A[Y]。 空块的和等于0

大和是任何块的最大和

例如,给定整数K=3、M=5和这样的数组 即:

例如,可以将阵列划分为以下块:

[2, 1, 5, 1, 2, 2, 2], [], [] with a large sum of 15;
[2], [1, 5, 1, 2], [2, 2] with a large sum of 9;
[2, 1, 5], [], [1, 2, 2, 2] with a large sum of 8;
[2, 1], [5, 1], [2, 2, 2] with a large sum of 6.
目标是最大限度地减少巨额金额。在上面的示例中,6是最小的大总和

编写一个函数:

class Solution { public int solution(int K, int M, int[] A); }
给定整数K,M和由N组成的非空数组a 整数,返回最小的大和

例如,给定K=3,M=5和数组A,使得:

A[0] = 2
A[1] = 1
A[2] = 5
A[3] = 1
A[4] = 2
A[5] = 2  
A[6] = 2
函数应该返回6,如上所述

为以下假设编写有效的算法:

  • N和K是[1..100000]范围内的整数;M是一个整数
  • 在[0..10000]范围内;数组A的每个元素都是一个整数
  • 在[0..M]范围内
下面的解决方案是:

public int解决方案(int K,int M,int[]A){
int min=0;
int max=0;
for(int i=0;i=A.length)
返回最小值;
int结果=min;
同时(分中){
总和=a[i];
k--;
}
如果(k==0)
返回false;
}
返回true;
}

该解决方案的思想非常简单:最小的大总和介于min(A)或sum(A)之间。我们可以使用二进制搜索来寻找最小和,而不是逐个迭代。对于每个候选块(mid),我们看是否有K个块不通过mid的值

我的问题是关于在上面的check()方法中基于中值查找块数的策略。有些情况下,块的数量符合标准,但没有一个块的总和等于中值。一个很好的例子是当我们有一个包含所有数组值的块,而其他块是空的

一个很好的例子是A=[2,3,3,5,4,2,3],K=3:中间值最终得到的值是10,我们可以有3个块[2,3,3],[5,4],[2,3],但它们都不等于10

解算算法是否可以输出一个中间值作为最小和,但该和实际上不存在?check()方法如何始终找到最小的大和,并且该最小的大和存在于数组中,而不将和值与中值进行比较

有些情况下,块的数量符合标准,但没有一个块的总和等于中值

这无关紧要,因为
check
将返回
true
,并且将检查较低的
mid
:一些较低的
mid
最终将等于某个块的和

一个很好的例子是A=[2,3,3,5,4,2,3],K=3:中间值最终得到的值是10,我们可以有3个块[2,3,3],[5,4],[2,3],但它们都不等于10

mid=10
check
返回
true
后,将执行:

max = mid - 1;
result = mid;
通过将
max
设置为
9
9
最终也将被检查并返回

解算算法是否可以输出一个中间值作为最小和,但该和实际上不存在

否,因为如果该总和不存在并且
check
返回
true
,则我们有一个可能的较小总和-因此当前
mid
不是最小值。如果算法得到100%,那么它将输出这个较小的值

还可以根据问题陈述中给出的定义来考虑:

大和是任何块的最大和

[……]

目标是最大限度地减少巨额金额。在上面的示例中,6是最小的大总和

因此,根据定义,最小和是某个块的和

check()方法如何始终找到最小的大和,并且该最小的大和存在于数组中,而不将和值与中值进行比较

check
方法本身不会找到最小的大总和。它只告诉您给定的和(其
mid
参数)是否有效(即,如果我们可以使用最大和将数组拆分为
K
块,谢谢。“不,因为如果该和不存在,并且check返回true,那么我们就有可能得到一个较小的和-因此当前的mid不是最小值。”对我来说是关键。最终mid将达到其中一个块的较小总和之一的值,因为之前的一个中值是有效的。
public int solution(int K, int M, int[] A) {

    int min = 0;
    int max = 0;

    for (int i = 0; i < A.length; i++) {
        max += A[i];
        min = Math.max(min, A[i]);
    }

    if (K == 1)
        return max;

    if (K >= A.length)
        return min;

    int result = min;

    while (min <= max) {

        int mid = (min + max) / 2;

        if (check(mid, K, A)) {

            max = mid - 1;
            result = mid;

        } else {

            min = mid + 1;

        }

    }

    return result;
}

private boolean check(int mid, int k, int[] a) {

    int sum = 0;

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

        sum += a[i];

        if (sum > mid) {
            sum = a[i];
            k--;
        }

        if (k == 0)
            return false;

    }

    return true;

}
max = mid - 1;
result = mid;