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