问题描述:
给出一个字符串,找到它的所有排列。
示例如:
输入'abc',
输出[ 'abc', 'acb', 'bac', 'bca', 'cab', 'cba' ]
输入'abb',
输出[ 'abb', 'bab', 'bba' ]
输入'abbc',
输出[
'abbc', 'abcb',
'acbb', 'babc',
'bacb', 'bbac',
'bbca', 'bcab',
'bcba', 'cabb',
'cbab', 'cbba'
]
参考https://blog.csdn.net/weixin_33912445/article/details/91421539
重点就是始终记住js是 “解释执行”的这个特点,执行是从上到下的。在没有异步的情况下,js代码是不能跳过前面的代码 去执行后面的代码的。也就是说递归的函数必须执行到最后,才能开始之后的代码
const Cstr = 'abc'
let Arr = Cstr.split('') //字符串转化为数组
function permutate(Arr){
let result = []
if(Arr.length > 1){ //若数组长度大于1,执行下一步
for(let i = 0; i < Arr.length; i++){
let temp = Arr[i] //取出当前字母
let newArr = permutate(Arr.slice(0,i).concat(Arr.slice(i+1,Arr.length))) //拼接除当前字母以外的字母成数组,并开始递归
for(let i = 0; i < newArr.length; i++){
result.push(temp + newArr[i].toString()) //当前字母加排列的字母组合
}
}
}else if(Arr.length === 1){
result.push(Arr)
}
return result
}
let finalArr = []
permutate(Arr).forEach(item => { //去重
if(!finalArr.some(item2 => item2 === item)){
finalArr.push(item)
}
})
console.log(finalArr);
流程梳理:(以字符串'abc'为例)
- 开始,temp等于a,数组拼接后得到[b,c],开启第一次递归
- [b,c]进入后,新的temp(2)等于b,数组拼接后得到[c],开启第二次递归
- [c]进入后,直接push到result里,第二次递归直接结束
- 返回到第一次递归,从第二次递归传递来的result为[[c]],即第一次递归的newArr为[[c]]
- 接着继续执行第一次递归的代码(从console.log(newArr);开始)
- 第一次temp(2)+newArr[i].toString为b+c,即bc,result此时为['bc']
- 同理第一次递归里大的for循环后可得到['cb']
- 第一次递归也结束,result此时为['bc','cb']
- 回到最开始,第一次递归的result给newArr,接着继续推进代码,即可得到['abc','acb']
- 然后外层for循环即可得到[ 'abc', 'acb', 'bac', 'bca', 'cab', 'cba' ]