1

I am working on permutation str using recursive, but it can not get out of the for loop. Can anyone help for this code? Thank you in advance.

    var permutations = [];
    var words = [];
    function getPerms(str) {
    
        if(str.length == 0) {
            permutations.push("");
            return permutations;
        }
        var first = str.charAt(0);//get the first char
        var reminder = str.slice(1);//remove the first char
        words = getPerms(reminder);
        for(var i = 0; i < words.length; i++) {
            for(var j = 0; j <= words[i].length; j++) {
                var s = insertCharAt(words[i], first, j);
                permutations.push(s);
            }
        }
        return permutations;
    }
    function insertCharAt(word, c, i) {
        var start = word.slice(0, i);
        var end = word.slice(i);
        var result = start + c + end;
        return result;
    }
    console.log(getPerms("abc"));
Robert
  • 369
  • 1
  • 7
  • 21
Sleepyhead
  • 105
  • 15

2 Answers2

1

Your code is fine, except for one issue:

The variables permutations should not be a global variable. You can clearly see this is wrong, by looking at permutations.push(""). This is fine as a temporary result in the deepest level of recursion, but obviously this should not be present in the final result. Yet, because permutations is global, and you never remove anything from it, permutations will keep this "".

The problem gets worse because words gets the permutations reference from the recursive call, and so they point to the very same array! So not only are all previous results iterated, but with an extra character add to them they are pushed again into permutations, which is the same array as words giving you an endless loop: you add to the array you are iterating, and so never get to the end.

The solution is simple:

Make permutations a variable local to the getPerms function. And why not do the same for words when you are at it.

function getPerms(str, depth=0) {
    var words = [];
    var permutations = [];

    if(str.length == 0) {
        permutations.push("");
        return permutations;
    }
    var first = str.charAt(0);//get the first char
    var reminder = str.slice(1);//remove the first char
    words = getPerms(reminder, depth+1);
    for(var i = 0; i < words.length; i++) {
        for(var j = 0; j <= words[i].length; j++) {
            var s = insertCharAt(words[i], first, j);
            permutations.push(s);
        }
    }
    return permutations;
}

function insertCharAt(word, c, i) {
    var start = word.slice(0, i);
    var end = word.slice(i);
    var result = start + c + end;
    return result;
}

console.log(getPerms("abc"));

Be sure to check these solutions offered for this problem.

trincot
  • 317,000
  • 35
  • 244
  • 286
0

The problem is probably at the last call you return permutations and then assign it to words (what you did here is like words = permutation), but this is not an assignement by copy, but by reference (because words and permutations belongs to the same scope + they are array), so from the last call they are the same object (and when the code unstack previous call, they are now the same object). To illustrate, execute the following code. You will see, when you modify words you modify permutations:

var permutations = [];
var words = [];
function getPerms(str) {

    if(str.length == 0) {
        permutations.push("");
        return permutations;
    }
    var first = str.charAt(0);//get the first char
    var reminder = str.slice(1);//remove the first char
    words = getPerms(reminder);
    words.push("foo");
    console.log( permutations);
    return permutations;
}
function insertCharAt(word, c, i) {
    var start = word.slice(0, i);
    var end = word.slice(i);
    var result = start + c + end;
    return result;
}
console.log(getPerms("abc"));

In your code, you loop on words and modify permutation in the same time (so, based on the previous explanation, it is like modifying words and loop on words in the same time), it is this things which create the infinite loop. I did not check if your algo works, I am just pointing code's problem. So I think what you want is:

     function getPerms(str) {

        var permutations = [];
        var words = [];
        if(str.length == 0) {
            permutations.push("");
            return permutations;
        }
        var first = str.charAt(0);//get the first char
        var reminder = str.slice(1);//remove the first char
        words = getPerms(reminder);
        for(var i = 0; i < words.length; i++) {
            for(var j = 0; j <= words[i].length; j++) {
                var s = insertCharAt(words[i], first, j);
                permutations.push(s);
            }
        }
        return permutations;
    }
    function insertCharAt(word, c, i) {
        var start = word.slice(0, i);
        var end = word.slice(i);
        var result = start + c + end;
        return result;
    }
    console.log(getPerms("abc"));
Ngob
  • 446
  • 4
  • 11