我试图从下面提供的Codility中的问题中了解解决方案,
对于来自集合{−1,1}的给定N个整数的数组A和N个整数的序列S,我们如下定义val(A,S):
val(A, S) = |sum{ A[i]*S[i] for i = 0..N−1 }|
(假设零个元素的总和等于零。)
对于给定的数组A,我们正在寻找使val(A,S)最小的序列S。
编写函数:
class Solution { public int solution(int[] A); }
,给定一个由N个整数组成的数组A,从集合{-1的N个整数的所有可能序列S中,根据val(A,S)的所有可能值计算val(A,S)的最小值。 1}。
例如,给定数组:
A[0] = 1
A[1] = 5
A[2] = 2
A[3] = -2
您的函数应该返回0,因为对于S = [-1,1,-1,1],val(A,S)= 0,这是可能的最小值。
假设:
N is an integer within the range [0..20,000];
each element of array A is an integer within the range [−100..100].
Complexity:
预期的最坏情况下的时间复杂度为O(N * max(abs(A))2); 预期的最坏情况下的空间复杂度为O(N + sum(abs(A)))(不计算输入参数所需的存储空间)。
在过去的几个小时中,我已经尝试了解了解决方案。
public static int solution(int[] A) {
int N = A.length;
int sum = 0;
int max = 0;
for (int i = 0; i < N; i++) {
A[i] = Math.abs(A[i]);
sum += A[i];
max = Math.max(A[i], max);
}
int[] counts = new int[max + 1];
for (int i = 0; i < N; i++) {
counts[A[i]] += 1;
}
int[] Total = new int[sum + 1];
Arrays.fill(Total, -1);
Total[0] = 0;
// Segment I
for (int i = 1; i <= max; i++) {
if (counts[i] > 0) {
for (int j = 0; j <= sum; j++) {
// j th index is zero or positive
if (Total[j] >= 0) {
Total[j] = counts[i];
}
// (i-j) th index is positive
else if ((j - i) >= 0 && Total[j - i] > 0) {
Total[j] = Total[j - i] - 1;
}
}
}
}
int result = sum;
// Segment II
for (int i = 0; i < sum / 2 + 1; i++) {
// i- th index if zero or positive
// BODMAS_RULE = {Brackets, Orders, Division, Multiplication, Addition, Subtraction}
if (Total[i] >= 0) {
result = Math.min(result, sum - 2 * i);
}
}
return result;
}
如果任何人都可以解释循环的最后两个部分中发生了什么,这将非常有帮助。我想在几行文字中寻找简短的解释。
我想了解为什么我们在第一段的for循环中使用条件。此外,为什么我们要迭代到第二个for循环中的sum / 2 + 1
。谢谢。
答案 0 :(得分:3)
要使用必需属性求和,您可以找到数组A的子集,其总和应尽可能接近总和的一半。
这是一种well-known postcss.config.js
,可以通过动态编程方法解决,方法是使用尺寸对应于总和的附加数组(注释数组subset sum problem
)。
请注意,该问题的解决方案仅处理正数,因此您必须对其进行修改以使用负数(例如您的示例Total
)。
此代码使数组A[3] = -2
的长度为total
,并保存数组sum+1
中每个值的计数。
在第一阶段,代码用所有可能的总和的非负数条目填充总计表。考虑简单的设置值:count counts
。
第一轮以值3,2,1,0填充条目0,2,4,6。
第二轮将所有非负输入项更改为三位数和
从非负条目(例如(2:3; 3:2)
)构建链的递减序列。之后,我们得到的数组4--> 4+3 ->4+6
的负数项(不可能的总和)为1,11。请注意,这种方法并不存储信息-使用了哪些项目来产生所有可能的总和,因此您必须进行更多修改。