Permutations
calls Permutations
again in a loop len
times. This second Permutations
call calls Permutations
again in a loop len
times. This happens again and again endlessly, or at least until you get a stack overflow.
When you use recursive calls, you always must make sure that the recursion stops somewhere.
If (job not done) {
make recursive call
}
The recursive call must make a step towards the completion of the job, otherwise it will never finish.
UPDATE 1 (only addressing the exception problem)
The method is difficult to read. Instead of repeating the expression len-1-k
several times, reverse the loop! for (int k = str.Length - 1; k >= 0; k--)
and decrease k
with k--
instead in the inner loop. I also got rid of the variable len
which is superfluous.
In your implementation len-1-k
is always >= 0
. Therefore the recursive calls will never end. Therefore I changed the condition for decreasing k
. It will decrease k
even if it is already 0
. In order not the get an index out of bounds error in str[k]
the condition k >= 0
must be checked first.
private static void Permutations(string str, string perm, int i)
{
if (i == str.Length)
Console.WriteLine(perm);
for (int k = str.Length - 1; k >= 0; k--) {
int lenPerm = perm.Length;
for (int j = 0; j < lenPerm; j++) {
if (k >= 0 && perm[j] == str[k])
k--;
}
if (k >= 0)
Permutations(str, perm + str[k], i++);
}
}
public static void Start()
{
string st = "123";
Permutations(st, "", 0);
}
This doesn't produce an endless recursion any more but the result is still not correct. I let you figure out how to improve the code further.
UPDATE 2 (creating correct permutations)
Finally here is my working implementation
public static class PermutationBuilder
{
private static char[] _characters;
private static List<string> _list;
public static IEnumerable<string> GetPermutations(string characters)
{
_characters = characters.ToCharArray();
_list = new List<string>();
AddPermutations("", 0);
return _list;
}
private static void AddPermutations(string permutation, int level)
{
if (level >= _characters.Length) {
_list.Add(permutation);
} else {
for (int i = 0; i < _characters.Length; i++) {
char ch = _characters[i];
if (ch != ' ') {
_characters[i] = ' ';
AddPermutations(permutation + ch, level + 1);
_characters[i] = ch;
}
}
}
}
}
Note that I temporarily mark the characters that have been used with a space character.
You call it like this
foreach (string permutation in PermutationBuilder.GetPermutations("123")) {
Console.WriteLine(permutation);
}