-
Notifications
You must be signed in to change notification settings - Fork 634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
百度&leetcode46:全排列问题 #102
Comments
本题是回溯算法的经典应用场景 1. 算法策略回溯算法是一种搜索法,试探法,它会在每一步做出选择,一旦发现这个选择无法得到期望结果,就回溯回去,重新做出选择。深度优先搜索利用的就是回溯算法思想。 2. 适用场景回溯算法很简单,它就是不断的尝试,直到拿到解。它的这种算法思想,使它通常用于解决广度的搜索问题,即从一组可能的解中,选择一个满足要求的解。 3. 代码实现我们可以写一下,数组 [1, 2, 3] 的全排列有:
即回溯的处理思想,有点类似枚举搜索。我们枚举所有的解,找到满足期望的解。为了有规律地枚举所有可能的解,避免遗漏和重复,我们把问题求解的过程分为多个阶段。每个阶段,我们都会面对一个岔路口,我们先随意选一条路走,当发现这条路走不通的时候(不符合期望的解),就回退到上一个岔路口,另选一种走法继续走。
这显然是一个 递归 结构;
let permute = function(nums) {
// 使用一个数组保存所有可能的全排列
let res = []
if (nums.length === 0) {
return res
}
let used = {}, path = []
dfs(nums, nums.length, 0, path, used, res)
return res
}
let dfs = function(nums, len, depth, path, used, res) {
// 所有数都填完了
if (depth === len) {
res.push([...path])
return
}
for (let i = 0; i < len; i++) {
if (!used[i]) {
// 动态维护数组
path.push(nums[i])
used[i] = true
// 继续递归填下一个数
dfs(nums, len, depth + 1, path, used, res)
// 撤销操作
used[i] = false
path.pop()
}
}
} 4. 复杂度分析
|
const permMutation = function (arr) {
let res = [];
if (arr.length <= 1) {
return arr;
}
for (let i = 0; i < arr.length; i++) {
let indexStr = arr[i];
let otherStr = [...arr.slice(0, i), ...arr.slice(i + 1)];
let tmp = permMutation(otherStr);
for (let j = 0; j < tmp.length; j++) {
res.push(Array.prototype.flat.call([indexStr, tmp[j]], Infinity));
}
}
return res;
} |
var permute = function(nums) {
let len = nums.length;
if(len === 0) return [[]];
let res = [];
let perm = function(arr, p, q, res){
if(p === q){
res.push([...arr])
}
for(let i = p; i <= q; i++){
swap(arr, i, p);
perm(arr, p+1, q, res);
swap(arr, i, p);
}
}
let swap = function(arr, left, right){
let temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
perm(nums, 0, len-1, res)
return res;
}; |
题解 循环数组内部元素: 2.dfs 全排列属于回溯入门问题,回溯还是需要多学多练 swap解法 var permute = function(nums) {
let len = nums.length;
if(len === 0) return [[]];
let res = [];
let perm = function(arr, p, q, res){
if(p === q){
res.push([...arr])
}
for(let i = p; i < q; i++){
swap(arr, i, p);
perm(arr, p+1, q, res);
swap(arr, i, p);
}
}
let swap = function(arr, left, right){
let temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
perm(nums, 0, len, res)
return res;
}; dfs解法 var permute = function(nums) {
let len = nums.length;
if(len === 0) return [[]];
let res = [];
let path = []; //维护动态数组
let used = {}; //保存已存在的元素
let dfs = function(arr, len, depth, path, used, res){
if(len === depth){
res.push([...path]);
return
}
for(let i = 0; i < len; i++){
if(!used[i]){
path.push(arr[i]);
used[i] = true;
dfs(arr, len, depth+1, path, used, res)
//状态回溯
used[i] = false;
path.pop();
}
}
}
dfs(nums, len, 0, path, used, res);
return res;
} |
const permute = nums => { function dfs (nth) { dfs(0); |
感觉递归函数不需参数也可以 function fn(arr) {
const path = [], used = {}
const res = []
const loopFn = () => {
if (path.length === arr.length) {
res.push([...path])
return
}
for (let i = 0, len = arr.length; i < len; i++){
if (!used[i]) {
path.push(arr[i])
used[i] = true
loopFn()
path.pop()
used[i] = false
}
}
}
loopFn()
return res
} |
|
/**
* 回溯算法
* @param {number[]} nums
*/
function permute(nums) {
let res = []
function dfs(track) {
// 到达决策树底部
if (track.length === nums.length) {
res.push([...track])
return
}
for (let num of nums) {
// 剪枝操作,避免重复遍历
if (track.includes(num)) {
continue
}
track.push(num)
dfs(track)
track.pop()
}
}
dfs([])
return res
}
console.log(permute([1,2,3])); |
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
附赠leetcode地址:leetcode
The text was updated successfully, but these errors were encountered: