我知道有很简单的方法来生成字符串中所有可能的字符排列,尤其是递归,但我发现了Steinhaus Johnson Trotter算法如何工作的非常清晰的描述here,并希望实现它忠实于Javascript。
为此,我为字符串中的每个字符创建了一个对象,其中“direction”属性可以从左向右更改。
代码可以工作,但就像,不可思议的长而且非常丑陋(例如,使用嵌套的if语句)。我会理解如何简化它。
function permutations(string) {
var letterArray = [];
var permutSolution = [string];
//Create objects for each character with initial position value and direction:
function letter(char, pos, dir) {
this.character = char;
this.position = pos;
this.direction = dir;
}
for (i = 0; i < string.length; i++) {
var newLetterObj = new letter(string[i], i, 'left');
letterArray.push(newLetterObj);
}
//function to identify the highest mobile character
function findHighestMC(value) {
return value.position == i;
}
//change the direction of characters with a higher position value than the current highest mobile character
function changeHigherMCDirection(element, index, array) {
if (element.position > i && element.direction == 'left') {
element.direction = 'right';
}
else if (element.position > i && element.direction == 'right') {
element.direction = 'left';
}
}
//run the algorithm through the input string
for (i = string.length -1; i > -1; i--) {
var highestMC = letterArray.filter(findHighestMC)[0]; //extract object from array
var highestMCIndex = letterArray.indexOf(highestMC);
if (highestMC.direction == 'left' && letterArray[highestMCIndex - 1] !== undefined && letterArray[highestMCIndex - 1].position < letterArray[highestMCIndex].position) {
var swap = letterArray[highestMCIndex];
letterArray[highestMCIndex] = letterArray[highestMCIndex - 1];
letterArray[highestMCIndex - 1] = swap;
var newPermut = letterArray.map(function(obj) {return obj.character;}).join('');
permutSolution.push(newPermut);
if (i == string.length - 1) {
i++;
}
else if (i < string.length - 1) {
letterArray.forEach(changeHigherMCDirection);
i = string.length;
}
}
else if (highestMC.direction == 'right' && letterArray[highestMCIndex + 1] !== undefined && letterArray[highestMCIndex + 1].position < letterArray[highestMCIndex].position) {
var swap = letterArray[highestMCIndex];
letterArray[highestMCIndex] = letterArray[highestMCIndex + 1];
letterArray[highestMCIndex + 1] = swap;
var newPermut = letterArray.map(function(obj) {return obj.character;}).join('');
permutSolution.push(newPermut);
if (i == string.length - 1) {
i++;
}
else if (i < string.length - 1) {
letterArray.forEach(changeHigherMCDirection);
i = string.length;
}
}
}
//remove duplicates from solution in case letters in input string aren't all unique
function deDupe (element, index, array) {
return array.indexOf(element) == index;
}
permutSolution = permutSolution.filter(deDupe);
return permutSolution;
}
console.log(permutations('abcd'))