Computing permutations (with duplicates) - divide and conquer →
In a previous post we saw how to write a recursive function to compute permutations of characters of a string. But we were computing redundant permutations when the input string had duplicated characters, as in the input string “AAB”. What could we do to avoid the redundant computations?
Intuitively we need to avoid some recursive calls that we know will lead to redundant computations. The sub-trees corresponding to this redundant computation are marked red in the sketch below:
What it indicates is that when we have the substring that we are processing (by walking through the characters in the substring) we look at the characters we process and decide if we want to go down that recursive path.
Let’s go through a couple of paths in the recursion tree above and try to figure this out:
-
(start:0, i:0)
: The string we are staring with isAAB
, substring starting atstart
isAAB
and substring starting ati
is alsoAAB
(asi
isstart
to begin with). Now we swaps[start]
ands[i]
which are bothA
. Now we call the _permute()
withstart
incremented by1
. a.(start:1, i:1..2)
: Now the substring starting atstart
isAB
(asstart
is1
) and substring starting ati
isAB
. Furthers[start]
isA
ands[i]
is alsoA
. We hence perform a swap producingAAB
and backtrack. Now,i:2
and sos[start]
isA
ands[i]
isB
. We swapA
andB
and getABA
. -
(start:0, i:1)
: The string we are staring with isAAB
, substring starting atstart
isAAB
and substring starting ati
is alsoAB
(asi
is1
now). We havesubstring_from_start
different fromsubstring_from_i
buts[start]
is the same ass[i]
which means that if we do a swap, we will yield the same thing and also we would have come across this earlier as we have processed the substring corresponding to thisi
. So we avoid going down this path and start working throughstart:0, i:2
.
So the condition we are looking for traversing is that substring(start)
and substring(i)
are same and further the starting character at start
and i
are the same. Further, if substring(start)
and substring(i)
are different and the starting characters are different, we go ahead with the traversal (as in start:0, i:2
).
Here is the modified permute()
function with the condition incorporated:
Hope you can refer to the sketch above, work through the example and feel convinced.