1. 题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串 abc,则打印出由字符 a,b,c 所能排列出来的所有字符串 abc,acb,bac,bca,cab 和 cba。
输入描述:输入一个字符串,长度不超过 9(可能有字符重复),字符只包括大小写字母。
2. 解题思路
把集合看成 2 个部分,第一部分是第一个元素,第二部分是后面剩余元素。所有字符都要与当前集合的第一个元素交换,交换后的元素是固定的,也就是一种情况。
每次交换,都继续处理后面剩余元素,它们又可以分成 2 部分,和之前讲述的一样。就这样一直递归下去,直到最后一个元素,那么就排出了其中一种情况。所有情况放在一起,就是全排列的结果。
3. 代码
let output = [];
/**
* 交换数组元素位置
* @param {Array} arr
* @param {Number} i
* @param {Number} j
*/
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
/**
* 检测arr(start, end)中, 是否有和arr[end]相等的元素, 过滤重复字符排列
* @param {Array} arr
* @param {Number} start
* @param {Number} end
*/
function check(arr, start, end) {
for (let i = start; i < end; i++) {
if (arr[end] === arr[i]) {
return false;
}
}
return true;
}
/**
* 递归排列
* @param {Array} arr
* @param {Number} n
*/
function perm(arr, n = 0) {
if (arr.length === n) {
output.push(arr.join(''));
return;
}
for (let i = n; i < arr.length; i++) {
if (check(arr, n, i)) {
// 将字符分成2部分,交换顺序
swap(arr, n, i);
perm(arr, n + 1);
// 排出一种排列后还原数组顺序
swap(arr, n, i);
}
}
}
/**
* 全排列
* @param {String} str
*/
function permutation(str) {
output = [];
if (str !== '') {
let arr = str.split('');
perm(arr);
}
return output.sort();
}
console.log(permutation('abc'));
console.log(permutation('abb'));