I think this is not feasible with your restrictions ( O(n) time and O(1) space, i.e. without extra space) for an array or array. (Assuming, of course, that we cannot just create a new List object, delegating the original one.)
If you have two linked lists, this is doable - if we assume that the garbage collector is fast enough, i.e. removing an item from one list and adding it to another list does not violate the space limit.
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 it is only O (n) for linked lists.
For a custom linked list where we can change pointers, we donβt need to rely on the garbage collector, we will just 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 will also have to adapt the pre-pointers.
Here's the packaging option 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); }
This is also O(1) .
PaΕlo Ebermann
source share