前端中的全排列算法

218 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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进行查找如果包含则把它插入到数组内,并执行回调,回调成功后则删除它,这就是入栈出栈临时的操作,循环遍历直到找不到后停止遍历

全排列是没有什么具体要求,只要解出即可