持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
前言
全排列在实际开发中而言是一个新的思路,它是由递归+回溯,进行实现,并且突出了树形结构,这个树形结构是天生递归的结构,它每个向下的分叉跟之前的逻辑可以保持一致,由于它比链表稍稍的复杂一点,但是要比链表好理解它的逻辑
全排列
比如给一个数字数组做全排列,并输出
var testString = [9,6,3]
在传统数学中,实际上这就是A33的排列码,分别左右挨个排列后的六种组合:
[9,6,3]
[9,3,6]
[6,9,3]
[6,3,9]
[3,9,6]
[3,6,9]
不过也可以用for嵌套的方式来解决,这种方式比较直接,根据排列组合来看,至少需要三层嵌套,如果数组的数子很多,这就不好实现,因为每个嵌套对应的是一种组合
全排列分解方式
在组合好的六个数组中,首先从每个组合数组中的第一个数字开始,就可以实现分叉,它本质上是一个树形结构,如果数据很多的可以以此类推
graph TB
A[开始]
A --> B[9]
A --> C[6]
A --> D[3]
B --> E[6]
B --> F[3]
C --> P[9]
C --> L[3]
D --> X[6]
D --> R[9]
E --> K[9]
E --> H[3]
F --> Y[6]
F --> Z[9]
P --> S[6]
P --> M[3]
现在已知它是树形结构,由于它是全排列,所以不知道它具体有多少种排列组合,这就可以结合回溯+递归思路来解决,手动对比是每个分叉的父级和子级别进行差找如何能组合成功,既正确
function setTest(nums){
let list = []
backtack(list,[],nums)
return list
}
function soCallback(list,temp,nums){
if(temp.length===nums.length){
return list.push(temp.slice())
}
for(let i=0;i<nums.length;i++){
if(!temp.includes(nums[i])){
temp.push(nums[i])
soCallback(result,temp,nums)
temp.pop()
}
continue
}
}
temp它是取每个数组的第一个,进行临时存储,然后的两位数通过每次递归的方式去找 通过includes进行查找如果包含则把它插入到数组内,并执行回调,回调成功后则删除它,这就是入栈出栈临时的操作,循环遍历直到找不到后停止遍历
全排列是没有什么具体要求,只要解出即可