List Swap
December 13, 2016
We have today an exercise for students who work with linked lists:
Given a linked list and an integer k, swap the two list items that are at distance k from the beginning of the list and distance k from the end of the list. Be sure to consider the case where the k cross, so that the item k from the beginning of the list is after the item k from the end of the list. For instance, given the list (1 2 3 4 5 6 7) and k = 2, you should return the list (1 6 3 4 5 2 7), and likewise if k = 6. The solution must run in O(n) time, where n is the length of the list.
Your task is to write the list-swapping code described above. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
This does up to five O(n) scans, which is still O(n), and works (without special consideration) when an item is swapped with itself or when the position from the beginning is further in the list than the position from the end, and (accidentally) even when both positions are outside the list. The auxiliaries use 0-based indexing. The solution is 1-based as in the spec.
It’s not difficult to do the swaps in place:
It looks like my C solution is pretty similar to Matthew’s C++. There’s really only one way to do it in the C family…
However, mine does detect cyclic lists and returns NULL for those.
Running it.
$ cc list-swap.c && a.out
{ 1 }
{ 2 1 }
{ 2 1 }
{ 3 2 1 }
{ 1 2 3 }
{ 3 2 1 }
{ 4 2 3 1 }
{ 1 3 2 4 }
{ 1 3 2 4 }
{ 4 2 3 1 }
{ 5 2 3 4 1 }
{ 1 4 3 2 5 }
{ 1 2 3 4 5 }
{ 1 4 3 2 5 }
{ 5 2 3 4 1 }
{ 6 2 3 4 5 1 }
{ 1 5 3 4 2 6 }
{ 1 2 4 3 5 6 }
{ 1 2 4 3 5 6 }
{ 1 5 3 4 2 6 }
{ 6 2 3 4 5 1 }
{ 7 2 3 4 5 6 1 }
{ 1 6 3 4 5 2 7 }
{ 1 2 5 4 3 6 7 }
{ 1 2 3 4 5 6 7 }
{ 1 2 5 4 3 6 7 }
{ 1 6 3 4 5 2 7 }
{ 7 2 3 4 5 6 1 }
@kernelbob: Pleased to be in good company. NIce point about circular lists. Here’s a version that should fix that (I don’t address the problem of freeing circular structures though). I’ve unrolled the loop once rather than use a flag variable: