Java: Interleaving multiple arrays into a single array
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;
}
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.
I've done up a small solution going on the assumption that you are talking about using the ArrayList
(see my comment on the question). I may be oversimplifying the problem based on some of the responses here, but here goes anyway.
The below example takes a and b both of type ArrayList<Integer>
and interleaves them by inserting b[0] after a[0], b[1] after a[1] etc. This snippet of course naively assumes that a and b are of the same size as per your Edit v1.0. It also does not create a new ArrayList
as per your Edit v2.0.
//a and b are of type ArrayList<Integer>
for (int i = a.size(); i > 0; i--)
{
a.add(i, b.get(i - 1));
}
No matter what happens if you are combining the ArrayLists you're going to have twice the size.