Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Interleaving multiple arrays into a single array

Tags:

java

arraylist

I found similar question about interleaving two arraylists into one, but its in PHP. I was asked this question in interview as well but could'nt solve it, came back to SO to look if it was addressed already, but i could only find this paper

So any pointers to pseudo code or method definition ?

Big(O) restrictions : O(n) - time cost and O(1) - space cost

Example:
a[]= a1, a2, ..., an
b[]= b1, b2, ..., bn
Rearrange the arraylist to a1, b1, a2, b2, ..., an, bn

Editv1.0 : Arraylists a[] and b[] are of same size

Editv2.0 : What if the question is extended to rearrange in one of given two arrays, but not create a new array ?

like image 572
SuperMan Avatar asked Apr 13 '11 18:04

SuperMan


People also ask

How do you combine arrays in Java?

In order to combine (concatenate) two arrays, we find its length stored in aLen and bLen respectively. Then, we create a new integer array result with length aLen + bLen . Now, in order to combine both, we copy each element in both arrays to result by using arraycopy() function.

What is interleaved array?

The Interleave 1D Arrays function takes two or more one-dimensional arrays and "interleaves" them into a single array by indexing the source arrays vertically before horizontally (take the first element of each source array, then take the second element of each source array, ...).

Can we concatenate two arrays?

The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

How do you add two int arrays in Java?

You can't add them directly, you have to make a new array and then copy each of the arrays into the new one. System. arraycopy is a method you can use to perform this copy. int[] array1and2 = new int[array1.


2 Answers

For simplicity, assume that the arrays are the same length, and are int arrays.

int[] merge(int[] a, int[] b)
{
    assert (a.length == b.length);

    int[] result = new int[a.length + b.length];

    for (int i=0; i<a.length; i++)
    {
        result[i*2] = a[i];
        result[i*2+1] = b[i];
    }

    return result;
}
like image 84
Matt Ball Avatar answered Nov 11 '22 14:11

Matt Ball


I think this is not doable with your given constraints (O(n) time and O(1) space, i.e. no additional space) for an array or array-based list. (Assuming of course, that we can't simply create a new List object delegating to the original ones.)

If you have two linked lists, this is doable - if we assume the garbage collector is fast enough, i.e. deleting an element from one list and adding it to another list does not violate the space limitation.

public <X> void interleaveLists(List<X> first, List<X> second)
{
    ListIterator<X> firstIt = first.listIterator();
    ListIterator<X> secondIt = second.listIterator();
    while(secondIt.hasNext()) {
        fistIt.next();
        firstIt.add(secondIt.next());
        secondIt.remove();
    }
}

This method works for any pair of lists, but is only O(n) for linked lists.

For a custom linked list where we can modify the pointers, we don't have to rely on the garbage collector, we would simply change the nodes. Here for a singly-linked list:

public void interleaveLinkedLists(Node<X> firstList, Node<X> secondList) {
    while(secondList != null) {
        Node<X> nextFirst = firstList.next;
        Node<X> nextSecond = secondList.next;
        firstList.next = secondList;
        secondList.next = nextFirst;
        firstList = nextFirst;
        secondList = nextSecond;
    }
}

For a doubly-linked list, we would also have to adapt the prev-pointers.

Here the wrapping variant mentioned in the first paragraph:

public List<X> interleaveLists(final List<X> first, final List<X> second)
{
   if (first.size() != second.size())
      throw new IllegalArgumentException();
   return new AbstractList<X>() {
      public int size() {
         return 2 * first.size();
      }
      public X get(int index) {
         return index % 2 == 0 ? first.get(index / 2) : second.get(index / 2);
      }
      // if necessary, add a similar set() method.  add/remove are not sensible here.
   };
}

This is actually O(1) in time, too.

like image 20
Paŭlo Ebermann Avatar answered Nov 11 '22 13:11

Paŭlo Ebermann