Split and Then Add Both Sides of an Array Together in Java


The challenge

You will receive an array as a parameter that contains 1 or more integers and a number n.

Here is a little visualization of the process:

  • Step 1: Split the array in two:[1, 2, 5, 7, 2, 3, 5, 7, 8] / \ [1, 2, 5, 7] [2, 3, 5, 7, 8]
  • Step 2: Put the arrays on top of each other: [1, 2, 5, 7] [2, 3, 5, 7, 8]
  • Step 3: Add them together:[2, 4, 7, 12, 15]

Repeat the above steps n times or until there is only one number left, and then return the array.

Examples

Input: arr=[4, 2, 5, 3, 2, 5, 7], n=2

Round 1
-------
step 1: [4, 2, 5]  [3, 2, 5, 7]

step 2:    [4, 2, 5]
        [3, 2, 5, 7]

step 3: [3, 6, 7, 12]

Round 2
-------
step 1: [3, 6]  [7, 12]

step 2:  [3,  6]
         [7, 12]

step 3: [10, 18]


Result: [10, 18]

The solution in Java code

Option 1:

import static java.util.Arrays.copyOfRange;

class Solution {
  static int[] splitAndAdd(int[] numbers, int n) {
    if (numbers.length > 1 && n > 0) {
      int[] half = copyOfRange(numbers, numbers.length / 2, numbers.length);
      for (int i = 0; i < numbers.length / 2; i++) {
        half[numbers.length % 2 > 0 ? i + 1 : i] += numbers[i];
      }
      return splitAndAdd(half, n - 1);
    }
    return numbers;
  }
}

Option 2:

public class Solution {
    public static int[] splitAndAdd(int[] arr, int n) {
        if (n<=0 || arr.length==1) return arr;
        int len = arr.length/2;
        int[] arr1 = new int[len], arr2 = new int[arr.length-len];
        System.arraycopy(arr, 0, arr1, 0, len);
        System.arraycopy(arr, len, arr2, 0, arr.length-len);
        int i = arr2.length - arr1.length;
        for (int a:arr1) arr2[i++] += a;
        return splitAndAdd(arr2, n-1);
    }
}

Option 3:

public class Solution {
    public static int[] splitAndAdd(int[] numbers, int n) {
        if (n == 0) return numbers;
        final int len = numbers.length;
        final int next[] = new int[(len+1)/2];
        for (int i = 0; i < next.length; i++) next[i] += numbers[len/2+i];
        for (int i = len/2-1, j=next.length-1; i >= 0; i--,j--) next[j] += numbers[i];
        return splitAndAdd(next, n-1);
    }
}

Test cases to validate our solution

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
import java.util.*;

public class TestClass {
    @Test
    public void splitAndAdd() throws Exception {
        
        int[] expected = new int[]{5,10};
        int[] input = Solution.splitAndAdd(new int[]{1,2,3,4,5},2);

        assertEquals(Arrays.toString(expected), Arrays.toString(input));

        expected = new int[]{15};
        input = Solution.splitAndAdd(new int[]{1,2,3,4,5},3);

        assertEquals(Arrays.toString(expected),Arrays.toString(input));
        
        expected = new int[]{15};
        input = Solution.splitAndAdd(new int[]{15},3);

        assertEquals(Arrays.toString(expected),Arrays.toString(input));
        
        expected = new int[]{183, 125};
        input = Solution.splitAndAdd(new int[]{32,45,43,23,54,23,54,34},2);

        assertEquals(Arrays.toString(expected),Arrays.toString(input));
        
        expected = new int[]{32,45,43,23,54,23,54,34};
        input = Solution.splitAndAdd(new int[]{32,45,43,23,54,23,54,34},0);

        assertEquals(Arrays.toString(expected),Arrays.toString(input));

        expected = new int[]{305, 1195};
        input = Solution.splitAndAdd(new int[]{3,234,25,345,45,34,234,235,345},3);

        assertEquals(Arrays.toString(expected),Arrays.toString(input));

        expected = new int[]{1040, 7712};
        input = Solution.splitAndAdd(new int[]{3,234,25,345,45,34,234,235,345,34,534,45,645,645,645,4656,45,3},4);

        assertEquals(Arrays.toString(expected),Arrays.toString(input));
        
        expected = new int[]{79327};
        input = Solution.splitAndAdd(new int[]{23,345,345,345,34536,567,568,6,34536,54,7546,456},20);
        
        assertEquals(Arrays.toString(expected),Arrays.toString(input));
    }
}