[英]Iterating a 2D Array using Java 8
这是0-1背包问题的实现。 问题陈述是这样的,
您将获得两个数组,一个数组包含一组项目的权重,另一个数组包含相应权重的值。 您已获得最大体重。 在不超过最大重量的约束范围内,确定通过选择或不选择一组项目可获得的最大值。 值和重量列表将始终具有相同的大小。
这是我的解决方案,通常可以正常工作(不适用于边缘情况)。
public static int getCombination(int[] weights, int[] values, int maxWeight){
int[][] memo = new int[weights.length][maxWeight + 1];
for (int i = 0; i < memo.length; i++) {
for(int j=0; j < memo[i].length; j++){
if(j == 0){
memo[i][j] = 0;
}else if(weights[i] > j){
if(i == 0) memo[i][j] = 0;
else memo[i][j] = memo[i-1][j];
}else{
if(i == 0){
memo[i][j] = values[i];
}
else{
memo[i][j] = Integer.max((values[i] + memo[i-1][j- weights[i]]), memo[i-1][j]);
}
}
}
}
return memo[weights.length -1][maxWeight];
}
现在,我想使用Java 8 Streams和lambda以声明的方式重新编写此完整逻辑。 有人可以帮我吗。
由于基于for循环的解决方案完全可以解决,因此,如果仅将for循环转换为forEach流,则流不会在此处增加太多价值。
如果使用IntStream
和toArray
方法,则可以从使用流中获得更多IntStream
,因为您可以专注于基于行和列索引来计算值,而不用担心将其填充到数组中。
int[][] memo = IntStream.range(0, rows)
.mapToObj(r -> IntStream.range(0, cols)
.map(c -> computeValue(r, c))
.toArray())
.toArray(int[rows][cols]::new);
在这里,我们为每一行创建一个数组,然后将它们放在最后的2D数组中。 如您所见, toArray()
方法负责填充数组。
实际上,既然我研究了您的方法来更紧密地计算值,我意识到在这种情况下即使不是不可能使用流也可能很困难。 问题是您需要以前的列和行中的值才能计算当前值。 在我的解决方案中这是不可能的,因为我们只在最后创建数组。 更具体地说,我的方法是无状态的,即您不记得先前迭代的结果。
您可以看到是否可以使用Stream.reduce()
来实现目标。
顺便说一句,你的方法很好。 如果您不想并行化它,那很好。
这是在数组中创建索引的可能起点:
int rows = 3;
int cols = 4;
int[][] memo = new int[rows][cols];
IntStream.range(0, rows * cols).forEach(n -> {
int i = n / cols;
int j = n % cols;
System.out.println("(" + i + "," + j + ")");
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.