07、JS实现:用回溯法实现数组全排列的算法(一步一步剖析,很详细)

Ⅰ、回溯法实现数组全排列:

1、题目描述:

给定⼀个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输⼊: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

2、解题思路:

以 [1,2,3] 为例,根据回溯思想,我们的逻辑是:
先从 [1,2,3] 选取⼀个数。
然后继续从 [1,2,3] 选取⼀个数,并且这个数不能是已经选取过的数。
重复这个过程直到选取的数字个数达到了 3。


可能存在的问题:
其一、如何确保这个数不能是已经选取过的数?
答:我们可以直接在已经选取的数字中线性查找,也可以将已经选取的数字中放到 hashset 中,这样就可以在
O(1)的时间来判断是否已经被选取了,只不过需要额外的空间;

3、实现代码:

其一、代码为:


// 此时的 list 是空数组、tempList 是空数组、nums 是没有重复数字的数组;
const backtrack = (list, tempList, nums) => {
   
   
  if (tempList.length === nums.length) return list.push([...tempList])
  for (let i = 0; i < nums.length; i++) {
   
   
    // 此时 continue 的作用:若 if() 满足条件,则会跳出本次的 for 循环;
    if (tempList.includes(nums[i])) continue
    tempList.push(nums[i])
    backtrack(list, tempList, nums)
    tempList.pop()
  }
}

const permute = (nums) => {
   
   
  const list = []
  backtrack(list, [], nums)
  return list
}


// 此时的输出结果为:[ [ 1, 2, 3 ], [ 1, 3, 2 ], [ 2, 1, 3 ], [ 2, 3, 1 ], [ 3, 1, 2 ], [ 3, 2, 1 ] ];
permute([1, 2, 3])




    执行  backtrack(list, [], nums)  函数后代码执行的过程(即:执行 backtrack([], [], [1,2,3]) 函数):
    
    注意:里面涉及多个循环嵌套递归,每次递归的出口为 tempList.length === nums.length,循环的出口为 for() 循环结束;


第一层循环,在 i=0 的情况下:
	if (tempList.includes(nums[i])) continue 的判断不成功;
	执行 tempList.push(nums[0]) 代码后,tempList 数组为 [1];
	backtrack(list, tempList, nums) 执行代码为:backtrack([], [1], [1,2,3])
	
	第二层循环,在 i=0 的情况下:
		if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;
		
	第二层循环,在 i=1 的情况下:
		if (tempList.includes(nums[i])) continue 的判断不成功;
		执行 tempList.push(nums[1]) 代码后,tempList 数组为 [1,2];
		backtrack(list, tempList, nums) 执行代码为:backtrack([], [1,2], [1,2,3])
		
		第三层循环,在 i=0 的情况下:
			if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;
			
		第三层循环,在 i=1 的情况下:
			if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;
			
		第三层循环,在 i=2 的情况下:
			if (tempList.includes(nums[i])) continue 的判断不成功;
			执行 tempList.push(nums[2]) 代码后,tempList 数组为 [1,2,3];
			backtrack(list, tempList, nums) 执行代码为:backtrack([], [1,2,3], [1,2,3])
			if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狮子座的男孩

如果可以,请我喝杯咖啡吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值