我们如何在 Java 中添加数组数字移位‽‽‽



我正在训练以下编程练习:以移位方式添加数组的值。该语句如下:

以转换的方式添加数组的值

你必须编写一个方法,它得到两个参数:

  1. 带有整数的数组数组
  2. 价值的转变

该方法应将数组的值添加到一个新数组中。

数组中的数组将具有相同的大小,此大小将 始终大于 0。移位值始终是从 0 开始的值 最大为数组的大小。数组中总是有数组,所以 您无需检查 null 或空。

1. 示例:

[[1,2,3,4,5,6], [7,7,7,7,7,7,-7]], 0

1,2,3,4,5,6 7,7,7,7,7,-7

--> [8,9,10,11,12,-1]

2. 示例

[[1,2,3,4,5,6], [7,7,7,7,7,7,7]], 3

1,2,3,4,5,6

7,7,7,7,7,7 --> [1,2,3,11,12,13,7,7,7]

3. 示例

[[1,2,3,4,5,6], [7,7,7,-7,7,7], [1,1,1,1,1,1]], 3

1,2,3,4,5,6 7,7,7,-7,7,7

1,1,1,1,1,1 --> [1,2,3,11,12,13,-6,8,8,1,1,1]

我在伪代码中想到了以下内容:

for each array of arrays
while shift > 0
Add to the result list the current number (they are the first numbers)
Add current number to next number (the one in the following array) into result
Add the last numbers to result
return result

我编写了以下 Java 代码:

import java.util.*;
import java.util.stream.*;
public class Kata
{
public static int[] addingShifted/*➕*/(int[][] arrayOfArrays, int shift)
{
System.out.println("nnnarrayOfArrays: "+Arrays.deepToString(arrayOfArrays));
System.out.println("shift: "+shift);
List<Integer> result = new ArrayList<Integer>();
int originalShift = shift;
for(int i = 0; i < arrayOfArrays.length; i++){
int[] current = arrayOfArrays[i];
int[] next = new int[0];
if(i < arrayOfArrays.length - 1){
next = arrayOfArrays[i+1];
}
for(int j = (i > 0) ? originalShift : 0; j < current.length; j++){
while(shift > 0){
result.add(current[j++]);
shift--;
}
System.out.println("j: "+j);
System.out.println("current[j]: "+current[j]);
System.out.println("next.length: "+next.length);
System.out.println("next[j-originalShift]: "+(next.length > 0 ? next[j-originalShift] : 0));
result.add(current[j] + (next.length > 0 ? next[j-originalShift] : 0));
System.out.println("result: "+Arrays.toString(result.toArray()));
}
if(originalShift == 0) break;
}
return result.stream().mapToInt(i->i).toArray();
}
}

我发现了一个测试,其中代码的输出与预期的不同:

arrayOfArrays: [[0, -9, -2, -8, 8, 2, 5, -5, 7, 1, -5, -9, -9, -1, 1, -2, -5, 9, -1, 9, 6, 2, -4, 4], [-4, -2, -8, 1, -6, -5, 8, 8, -7, -3, -6, -8, 5, 6, 1, 0, -2, -1, 5, 3, -9, -2, 4, -3], [-7, 3, 5, -3, 2, 2, 0, -6, 6, 7, 0, 9, 0, -6, -8, 6, -3, -5, -2, -4, -7, -4, -7, 1], [5, -6, 8, 5, 1, -2, -8, 5, 7, -5, 6, -3, 0, 7, -4, 6, -7, -8, 0, 2, 8, 5, -1, -3], [-7, -4, 7, 0, 0, -1, 3, 0, -5, 5, -5, -3, -7, -5, -9, -4, -5, -8, -5, 9, 0, 8, 8, -7], [5, 8, 2, 0, 3, -3, 2, -2, 6, -5, -6, -8, 4, -7, 9, 3, 4, -6, -7, 4, -8, -9, -3, -9], [9, 8, -2, -8, 8, -1, 6, 6, 0, -7, 9, 9, 2, 3, -7, 9, 4, -8, 8, -2, -2, 7, 9, 2]]
shift: 2
Expected: [0, -9, -6, -10, [-7, 6, 9, -19, 18, 12, 1, -12, -6, 10, 17, -3, 7, 2, -4, 19, -9, -14, -18, -12, 3, -7, -7, 18, -4, 1, 8, -18, -5, -2], 9, 2]
Code's output: [0, -9, -6, -10, [0, 3, -1, -10, 15, 9, -12, -12, -15, -9, 6, 4, -4, 9, -3, 8, 11, 5, -13, 2, -15, 4, -1, -8, 10, 10, -7, -9, 0, -1, 5, 15, 1, -6, -10, 5, 2, -2, -11, -6, -3, -7, 10, -9, 10, 7, 1, -8, -2, 12, 7, 4, 6, -9, -8, 13, -7, 1, -9, -12, -7, -2, 1, 6, 1, 1, 8, -2, -8, 4, 10, -5, 1, 2, -5, 4, -11, 1, -16, -12, -5, -6, 3, 14, -1, 5, 12, 8, 2, -1, 6, -3, -3, 3, 1, -8, -13, -13, -5, -11, 4, -5, -1, 3, -7, 12, 0, -16, 11, 8, 1, -11, 10, -3, 12, 1, -6, -15, 13, 2, 11, 6, -3, 3, -3, -4, 0, -11, -5, -2, -2, -8, 8, -1, 6, 6, 0, -7, 9, 9, 2, 3, -7, 9, 4, -8, 8, -2, -2, 7], 9, 2]

跟踪开始如下:

j: 2
current[j]: -2
next.length: 24
next[j-originalShift]: -4
result: [0, -9, -6]
j: 3
current[j]: -8
next.length: 24
next[j-originalShift]: -2
result: [0, -9, -6, -10]
j: 4
current[j]: 8
next.length: 24
next[j-originalShift]: -8
result: [0, -9, -6, -10, 0]
j: 5
current[j]: 2
next.length: 24
next[j-originalShift]: 1
result: [0, -9, -6, -10, 0, 3]

我们观察到,我们的代码和预期结果不同的第一个结果是 j: 4,所以期望值是:-7,但它计算的是 0 (8-8(。

此外,我们看到输出的数字比预期结果多得多。

我想知道为什么前面两个事实都会发生!?

我们如何改进代码‽‽‽

有没有更简单、更清晰、更易读的答案‽‽‽

我问,因为我发布的代码通过了以下测试(从练习的测试中提取(:

import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.*;
import org.junit.runners.JUnit4;
public class SolutionTest {
@Test
public void basicTests() {        
int[][] arrayOfArrays = new int[][] { new int[] { 1, 2, 3, 4, 5, 6 }, new int[] { 7, 7, 7, 7, 7, 7 } };
int[] expected = new int[] { 8, 9, 10, 11, 12, 13 };
int[] result = Kata.addingShifted(arrayOfArrays, 0);
assertNotNull(result);
assertEquals(Arrays.toString(expected), Arrays.toString(result));
arrayOfArrays = new int[][] { new int[] { 1, 2, 3, 4, 5, 6 }, new int[] { 7, 7, 7, 7, 7, 7 } };
expected = new int[] { 1, 2, 3, 11, 12, 13, 7, 7, 7 };
result = Kata.addingShifted(arrayOfArrays, 3);
assertNotNull(result);      
assertEquals(Arrays.toString(expected), Arrays.toString(result));
arrayOfArrays = new int[][] { new int[] { 1, 2, 3, 4, 5, 6 }, new int[] { 7, 7, 7, -7, 7, 7 }, new int[] { 1, 1, 1, 1, 1, 1 } };
expected = new int[] { 1, 2, 3, 11, 12, 13, -6, 8, 8, 1, 1, 1 };
result = Kata.addingShifted(arrayOfArrays, 3);
assertNotNull(result);
assertEquals(Arrays.toString(expected), Arrays.toString(result));
}
}

但是,正如我们所看到的,它在更大的阵列上存在困难。为什么‽

我还读过:

  • 如何在 Java 中将 List转换为 int[]?
  • Java - 打印 2D 数组的最佳方法?
  • Java:如何对两个不同长度的数组的元素求和
  • 长数组的精确总和

这是一个更简单、更干净的解决方案:

public static int[] addingShifted(int[][] input, int shift) {
int[] result = new int[input[0].length + shift * (input.length - 1)];
for (int i = 0; i < input.length; i++)
for (int j = 0; j < input[i].length; j++)
result[i * shift + j] += input[i][j];
return result;
}

测试

System.out.println(Arrays.toString(addingShifted(new int[][] {{1,2,3,4,5,6}, {7,7,7,7,7,-7}}, 0)));
System.out.println(Arrays.toString(addingShifted(new int[][] {{1,2,3,4,5,6}, {7,7,7,7,7,7}}, 3)));
System.out.println(Arrays.toString(addingShifted(new int[][] {{1,2,3,4,5,6}, {7,7,7,-7,7,7}, {1,1,1,1,1,1}}, 3)));

输出

[8, 9, 10, 11, 12, -1]
[1, 2, 3, 11, 12, 13, 7, 7, 7]
[1, 2, 3, 11, 12, 13, -6, 8, 8, 1, 1, 1]