When I went for interview at Imperial College, my interviewer (Dr. P. Kelly) asked me quite a nice question, which (for some unearthly reason) I decided to follow up on afterwards.
The question was a simple one: given a string (e.g.) "examplesgnome" consisting of two substrings (in this case, "examples" and "gnome"), how can we swap the two substrings in-place? In the interview, we covered the third method in more detail, but touched upon the other two. Afterwards, I calculated their computational efficiency, and determined while they all have the same upper bound, one has a lower average running time.
Method one: reversal
This is one Dr. Kelly suggested, which is really rather neat. It consists of two steps: reversing the entire string, then reversing both substrings. For example:
- examplesgnome
- emongselpmaxe
- gnomeexamples
If we take
n
to equal the total number of characters,
a
to equal the number of characters in the smaller substring, and
b
to equal the number of characters in the larger substring, this has:
\left\lfloor \frac{n}{2} \right\rfloor + \left\lfloor \frac{a}{2} \right\rfloor + \left\lfloor \frac{b}{2} \right\rfloor
swaps, so we may as well say it's of linear complexity
O(n)
.
Method two: cycles
This one was also suggested by Dr. Kelly, and involves taking the first character of the larger substring out to a temporary location, then cyclically moving characters
b
places along into the generated space. Once the strings have been swapped (
n
swaps have taken place), we put the stored character back in the final space. For example:
- examplesgnome
- _xamplesgnome
- gxamples_nome
- gxa_plesmnome
- gxamplesmno_e
- gxampl_smnoee
- g_amplxsmnoee
- gnamplxsm_oee
- gnam_lxsmpoee
- gnamelxsmpoe_
- gnamelx_mpoes
- gn_melxampoes
- gnomelxamp_es
- gnome_xamples
- gnomeexamples
Since each character moves to its final position in one move, the algorithm is intuitively of complexity
O(n)
— but we can go further and say it's of absolute complexity
\sim (n + 2)
, taking the steps to remove the first character and fill the last space into account.
Method three: reduction
This is the method I came up with during the interview and, with some help, made work. It basically involves swapping the first smaller substring into its final position, then applying the same algorithm to the resulting subsubstrings of the second substring. For example:
- examplesgnome
gnomelesexamp
gnomeampexles
gnomeexpamles
gnomeexmaples
- gnomeexamples
This is quite a neat one to implement, and will perform
O(n)
swaps in the worst case (when the smaller substring is only one character long, as one character moves to its final position with each swap).
However, what if we consider the case "foobar", where the substrings are "foo" and "bar"? In this case, method three only takes 3 swaps. Obviously, this method is limited in the upper bound to
O(n)
swaps, but it seems it can do the operation in far fewer — as few as
\Omega (a)
.
I haven't got a concrete proof for this, but I believe this is actually of complexity:
\sim (a \left\lfloor \frac{b}{a} \right\rfloor + (b \bmod{a}) \left\lfloor \frac{a}{b \bmod{a}} \right\rfloor)
as the lengths of the substring for each iteration
i
depend on the remainder of
\frac{b}{a}
for the
i - 1
th iteration. This complexity can be manipulated to prove that it's also of complexity
O(n)
:

All-in-all, I'm quite pleased with the interview: even if I'm not successful, it's given me an interesting problem to consider. Corrections and further thoughts on the problem are welcomed.