跳到主要内容

17 篇博文 含有标签「回溯」

查看所有标签

· 阅读需 3 分钟

1、题干

给你一个由正整数组成的数组 nums 和一个 整数 k

如果 nums 的子集中,任意两个整数的绝对差均不等于 k ,则认为该子数组是一个 美丽 子集。

返回数组 nums非空美丽 的子集数目。

nums 的子集定义为:可以经由 nums 删除某些元素(也可能不删除)得到的一个数组。只有在删除元素时选择的索引不同的情况下,两个子集才会被视作是不同的子集。

 

示例 1:

输入:nums = [2,4,6], k = 2
输出:4
解释:数组 nums 中的美丽子集有:[2], [4], [6], [2, 6] 。
可以证明数组 [2,4,6] 中只存在 4 个美丽子集。

示例 2:

输入:nums = [1], k = 1
输出:1
解释:数组 nums 中的美丽数组有:[1] 。
可以证明数组 [1] 中只存在 1 个美丽子集。

 

提示:

  • 1 <= nums.length <= 20
  • 1 <= nums[i], k <= 1000

2、思路

BFS暴力枚举,时间爆炸,有空再优化,下次一定

3、代码

function beautifulSubsets(nums: number[], k: number): number {
const hash = new Array(nums.length).fill(0).map(() => new Array(nums.length).fill(0))
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (Math.abs(nums[j] - nums[i]) === k) hash[i][j] = 1;
}
}

let queue = nums.map((v, i) => [i]), ans = 0;
while (queue.length) {
const next = [];
for (const q of queue) {
ans++;
for (let j = q.at(-1) + 1; j < nums.length; j++) {
if (q.every((i) => !hash[i][j])) next.push([...q, j]);
}
}
queue = next;
}

return ans;
};

4、执行结果

image.png

· 阅读需 4 分钟

1、题干

如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串。

花括号展开的表达式可以看作一个由 花括号逗号小写英文字母 组成的字符串,定义下面几条语法规则:

  • 如果只给出单一的元素 x,那么表达式表示的字符串就只有 "x"R(x) = {x}
    • 例如,表达式 "a" 表示字符串 "a"
    • 而表达式 "w" 就表示字符串 "w"
  • 当两个或多个表达式并列,以逗号分隔,我们取这些表达式中元素的并集。R({e_1,e_2,...}) = R(e_1) ∪ R(e_2) ∪ ...
    • 例如,表达式 "{a,b,c}" 表示字符串 "a","b","c"
    • 而表达式 "{{a,b},{b,c}}" 也可以表示字符串 "a","b","c"
  • 要是两个或多个表达式相接,中间没有隔开时,我们从这些表达式中各取一个元素依次连接形成字符串。R(e_1 + e_2) = {a + b for (a, b) in R(e_1) × R(e_2)}
    • 例如,表达式 "{a,b}{c,d}" 表示字符串 "ac","ad","bc","bd"
  • 表达式之间允许嵌套,单一元素与表达式的连接也是允许的。
    • 例如,表达式 "a{b,c,d}" 表示字符串 "ab","ac","ad"​​​​​​
    • 例如,表达式 "a{b,c}{d,e}f{g,h}" 可以表示字符串 "abdfg", "abdfh", "abefg", "abefh", "acdfg", "acdfh", "acefg", "acefh"

给出表示基于给定语法规则的表达式 expression,返回它所表示的所有字符串组成的有序列表。

假如你希望以「集合」的概念了解此题,也可以通过点击 “显示英文描述” 获取详情。

 

示例 1:

输入:expression = "{a,b}{c,{d,e}}"
输出:["ac","ad","ae","bc","bd","be"]

示例 2:

输入:expression = "{{a,z},a{b,c},{ab,z}}"
输出:["a","ab","ac","z"]
解释:输出中 不应 出现重复的组合结果。

 

提示:

  • 1 <= expression.length <= 60
  • expression[i]'{''}'',' 或小写英文字母组成
  • 给出的表达式 expression 用以表示一组基于题目描述中语法构造的字符串

2、思路

本题要处理的子表达式主要包括3类:

  • 单层:{xxx,xxx}
  • 嵌套:{{xxx},{xxx}}
  • 相接:{xxx}{xxx}xxx{xxx}{xxx}xxx

具体代码实现逻辑如下:

  • 扁平化:把最内层的单层表达式提取到上一层(这会逐渐把嵌套和单层表达式都处理掉)
  • 拼接组合:拼接组合最内层相接子表达式
  • 重复这两个步骤直到表达式中没有任何花括号
  • 最后对表达式进行拆分、去重、排序

3、代码

function braceExpansionII(exp: string): string[] {
const reg0 = /\{([a-z,]+)\}/g;
const reg1 = new RegExp(`(?<![a-z}])${reg0.source}(?![a-z{])`, 'g');
const reg2 = new RegExp(`(${reg0.source}){2,}|[a-z]+(${reg0.source})+|(${reg0.source})+[a-z]+`, 'g');

while (1) {
const f1 = reg1.test(exp);
if (f1) exp = exp.replace(reg1, '$1');

const f2 = reg2.test(exp);
if (f2) {
exp = exp.replace(reg2, (m) => {
const reg = new RegExp(`${reg0.source}|[a-z]+`, 'g');

const tokenGroup = (m.match(reg) || []).map(s => s.split(/,|\{|\}/).filter(Boolean));

let ans = tokenGroup[0];
for (let i = 1; i < tokenGroup.length; i++) {
const newAns = [];
for (const h of ans) {
for (const t of tokenGroup[i]) {
newAns.push(h + t);
}
}
ans = newAns;
}

return `{${ans.join(',')}}`
});
}

if (!f1 && !f2) break;
}

return [...new Set(exp.split(','))].sort();
};

4、执行结果

image.png

· 阅读需 4 分钟

1、题干

你将会得到一份单词表 words,一个字母表 letters (可能会有重复字母),以及每个字母对应的得分情况表 score

请你帮忙计算玩家在单词拼写游戏中所能获得的「最高得分」:能够由 letters 里的字母拼写出的 任意 属于 words 单词子集中,分数最高的单词集合的得分。

单词拼写游戏的规则概述如下:

  • 玩家需要用字母表 letters 里的字母来拼写单词表 words 中的单词。
  • 可以只使用字母表 letters 中的部分字母,但是每个字母最多被使用一次。
  • 单词表 words 中每个单词只能计分(使用)一次。
  • 根据字母得分情况表score,字母 'a''b''c', ... , 'z' 对应的得分分别为 score[0], score[1], ..., score[25]
  • 本场游戏的「得分」是指:玩家所拼写出的单词集合里包含的所有字母的得分之和。

 

示例 1:

输入:words = ["dog","cat","dad","good"], letters = ["a","a","c","d","d","d","g","o","o"], score = [1,0,9,5,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0]
输出:23
解释:
字母得分为 a=1, c=9, d=5, g=3, o=2
使用给定的字母表 letters,我们可以拼写单词 "dad" (5+1+5)和 "good" (3+2+2+5),得分为 23 。
而单词 "dad" 和 "dog" 只能得到 21 分。

示例 2:

输入:words = ["xxxz","ax","bx","cx"], letters = ["z","a","b","c","x","x","x"], score = [4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,10]
输出:27
解释:
字母得分为 a=4, b=4, c=4, x=5, z=10
使用给定的字母表 letters,我们可以组成单词 "ax" (4+5), "bx" (4+5) 和 "cx" (4+5) ,总得分为 27 。
单词 "xxxz" 的得分仅为 25 。

示例 3:

输入:words = ["leetcode"], letters = ["l","e","t","c","o","d"], score = [0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0]
输出:0
解释:
字母 "e" 在字母表 letters 中只出现了一次,所以无法组成单词表 words 中的单词。

 

提示:

  • 1 <= words.length <= 14
  • 1 <= words[i].length <= 15
  • 1 <= letters.length <= 100
  • letters[i].length == 1
  • score.length == 26
  • 0 <= score[i] <= 10
  • words[i] 和 letters[i] 只包含小写的英文字母。

2、思路

回溯,枚举所有情况计算最高得分。未优化,存在重复计算,效率不高。

3、代码

function maxScoreWords(words: string[], letters: string[], score: number[]): number {
const wordScore = new Array(words.length).fill(0);
for (let i = 0; i < words.length; i++) {
for (let j = 0; j < words[i].length; j++) {
wordScore[i] += score[words[i][j].charCodeAt(0) - 97];
}
}

const letterDict = new Array(26).fill(0);
for (let i = 0; i < letters.length; i++) {
letterDict[letters[i].charCodeAt(0) - 97] += 1;
}

let ans = 0;
function dfs(sc: number, visited: Set<number>) {
for (let i = 0; i < words.length; i++) {
if (visited.has(i)) continue;

let valid = true;
for (let j = 0; j < words[i].length; j++) {
const c = words[i][j].charCodeAt(0) - 97;
letterDict[c]--;
if (letterDict[c] < 0) valid = false;
}

if (valid) {
ans = Math.max(ans, sc + wordScore[i]);

visited.add(i);
dfs(sc + wordScore[i], visited);
visited.delete(i);
}

for (let j = 0; j < words[i].length; j++) {
letterDict[words[i][j].charCodeAt(0) - 97]++;
}
}
}

return dfs(0, new Set()), ans;
};

4、执行结果

image.png

· 阅读需 3 分钟

1、题干

给你两个整数 nstart。你的任务是返回任意 (0,1,2,,...,2^n-1) 的排列 p,并且满足:

  • p[0] = start
  • p[i]p[i+1] 的二进制表示形式只有一位不同
  • p[0]p[2^n -1] 的二进制表示形式也只有一位不同

 

示例 1:

输入:n = 2, start = 3
输出:[3,2,0,1]
解释:这个排列的二进制表示是 (11,10,00,01)
所有的相邻元素都有一位是不同的,另一个有效的排列是 [3,1,0,2]

示例 2:

输入:n = 3, start = 2
输出:[2,6,7,5,4,0,1,3]
解释:这个排列的二进制表示是 (010,110,111,101,100,000,001,011)

 

提示:

  • 1 <= n <= 16
  • 0 <= start < 2^n

2、思路1

没啥思路先尝试暴力枚举,这里用回溯实现。从整数 start 开始枚举下一个可能的整数,用 202^0, 212^1 ... 2n12^{n-1} 分别与 start 做异或运算即可得到,递归重复这个过程得到结果。

3、代码

function circularPermutation(n: number, start: number): number[] {
let ans = [], visited = new Set<number>();

function dfs(i: number) {
if (ans.length || visited.size > 2 ** n || visited.has(i)) return;

visited.add(i);
if (visited.size === 2 ** n) return ans = [...visited];

for (let b = 0; b < n; b++) {
dfs(1 << b ^ i);
}

visited.delete(i);
}

return dfs(start), ans;
};

4、执行结果

image.png

5、思路2

先生成格雷码,再以 start 为起点偏移得到结果

6、代码

function circularPermutation(n: number, start: number): number[] {
const ans = [0, 1];

for (let h = 1; h < n; h++) {
for (let i = ans.length - 1; i > -1; i--) {
ans.push(1 << h | ans[i]);
}
}

const i = ans.indexOf(start);
if (!i) return ans;

return [...ans.slice(i), ...ans.slice(0, i)];
};

7、复杂度

  • 时间复杂度:O(2n)O(2^n)
  • 空间复杂度:O(n)O(n)

8、执行结果

image.png

· 阅读需 4 分钟

1、题干

你打算做甜点,现在需要购买配料。目前共有 n 种冰激凌基料和 m 种配料可供选购。而制作甜点需要遵循以下几条规则:

  • 必须选择 一种 冰激凌基料。
  • 可以添加 一种或多种 配料,也可以不添加任何配料。
  • 每种类型的配料 最多两份

给你以下三个输入:

  • baseCosts ,一个长度为 n 的整数数组,其中每个 baseCosts[i] 表示第 i 种冰激凌基料的价格。
  • toppingCosts,一个长度为 m 的整数数组,其中每个 toppingCosts[i] 表示 一份i 种冰激凌配料的价格。
  • target ,一个整数,表示你制作甜点的目标价格。

你希望自己做的甜点总成本尽可能接近目标价格 target

返回最接近 target 的甜点成本。如果有多种方案,返回 成本相对较低 的一种。

 

示例 1:

输入:baseCosts = [1,7], toppingCosts = [3,4], target = 10
输出:10
解释:考虑下面的方案组合(所有下标均从 0 开始):
- 选择 1 号基料:成本 7
- 选择 1 份 0 号配料:成本 1 x 3 = 3
- 选择 0 份 1 号配料:成本 0 x 4 = 0
总成本:7 + 3 + 0 = 10 。

示例 2:

输入:baseCosts = [2,3], toppingCosts = [4,5,100], target = 18
输出:17
解释:考虑下面的方案组合(所有下标均从 0 开始):
- 选择 1 号基料:成本 3
- 选择 1 份 0 号配料:成本 1 x 4 = 4
- 选择 2 份 1 号配料:成本 2 x 5 = 10
- 选择 0 份 2 号配料:成本 0 x 100 = 0
总成本:3 + 4 + 10 + 0 = 17 。不存在总成本为 18 的甜点制作方案。

示例 3:

输入:baseCosts = [3,10], toppingCosts = [2,5], target = 9
输出:8
解释:可以制作总成本为 8 和 10 的甜点。返回 8 ,因为这是成本更低的方案。

示例 4:

输入:baseCosts = [10], toppingCosts = [1], target = 1
输出:10
解释:注意,你可以选择不添加任何配料,但你必须选择一种基料。

 

提示:

  • n == baseCosts.length
  • m == toppingCosts.length
  • 1 <= n, m <= 10
  • 1 <= baseCosts[i], toppingCosts[i] <= 104
  • 1 <= target <= 104

Problem: 1774. 最接近目标价格的甜点成本

2、思路

暴力搜索,确定基料,枚举配料

3、Code

function closestCost(baseCosts: number[], toppingCosts: number[], target: number): number {
let ans = baseCosts[0];

function dfs(c: number, ti: number) {
if (c === target) return ans = target;
else {
const d1 = Math.abs(c - target), d2 = Math.abs(ans - target);
if (d1 < d2 || (d1 === d2 && c < ans)) ans = c;
}

for (let i = ti; i < toppingCosts.length && c <= target; i++) {
for (let k = 0; k < 3; k++) dfs(c + k * toppingCosts[i], i + 1);
}
}

for (const b of baseCosts) dfs(b, 0);

return ans;
};

4、执行结果

image.png

· 阅读需 3 分钟

1、题干

我们有一些二维坐标,如 "(1, 3)" 或 "(2, 0.5)",然后我们移除所有逗号,小数点和空格,得到一个字符串S。返回所有可能的原始字符串到一个列表中。

原始的坐标表示法不会存在多余的零,所以不会出现类似于"00", "0.0", "0.00", "1.0", "001", "00.01"或一些其他更小的数来表示坐标。此外,一个小数点前至少存在一个数,所以也不会出现“.1”形式的数字。

最后返回的列表可以是任意顺序的。而且注意返回的两个数字中间(逗号之后)都有一个空格。

 

示例 1:
输入: "(123)"
输出: ["(1, 23)", "(12, 3)", "(1.2, 3)", "(1, 2.3)"]
示例 2:
输入: "(00011)"
输出:  ["(0.001, 1)", "(0, 0.011)"]
解释:
0.0, 00, 0001 或 00.01 是不被允许的。
示例 3:
输入: "(0123)"
输出: ["(0, 123)", "(0, 12.3)", "(0, 1.23)", "(0.1, 23)", "(0.1, 2.3)", "(0.12, 3)"]
示例 4:
输入: "(100)"
输出: [(10, 0)]
解释:
1.0 是不被允许的。

 

提示:

  • 4 <= S.length <= 12.
  • S[0] = "(", S[S.length - 1] = ")", 且字符串 S 中的其他元素都是数字。

 

Problem: 816. 模糊坐标

[TOC]

思路

  • 剔除原始字符串 s 中的括号
  • s 拆分成两个字符串 s1s2
  • 分别对 s1s2 添加小数点,得到两个字符串数组 nums1nums2
  • 组合 nums1nums2 中的字符串得到最终结果

复杂度

  • 时间复杂度:O(n3)O(n^3)
  • 空间复杂度:O(n3)O(n^3)

Code


function ambiguousCoordinates(s: string): string[] {
s = s.slice(1, s.length - 1);

const res = [];

function insertDot(str: string) {
const nums = /^0\d/.test(str) ? [] : [str];

for (let j = 1; j < str.length; j++) {
const ns = str.slice(0, j) + '.' + str.slice(j);
if (!/^0\d|0$/.test(ns)) nums.push(ns);
}

return nums;
}

for (let i = 1; i < s.length; i++) {
const s1 = s.slice(0, i), s2 = s.slice(i);
const nums1 = insertDot(s1), nums2 = insertDot(s2);

for (const ns1 of nums1) {
for (const ns2 of nums2) {
res.push(`(${ns1}, ${ns2})`);
}
}
}

return res;
}

· 阅读需 3 分钟

1、题干

给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。

返回所有可能的结果。答案可以按 任意顺序 返回。

 

示例 1:

输入:s = "()())()"
输出:["(())()","()()()"]

示例 2:

输入:s = "(a)())()"
输出:["(a())()","(a)()()"]

示例 3:

输入:s = ")("
输出:[""]

 

提示:

  • 1 <= s.length <= 25
  • s 由小写英文字母以及括号 '('')' 组成
  • s 中至多含 20 个括号

深圳阿里Lazada笔试题T4,30min钟4道题,这道题没时间写

1d58c1fc375efb4172fc38ed625cfb94.gif


2、解题思路

回溯+剪枝枚举所有可行的情况,遍历过程中判断合法子串只需要判断已选子串长度不为0且左括号被消耗完即 lc=0,详细逻辑见注释


3、代码

var removeInvalidParentheses = function (s) {
let res = [''];

// 初始状态:字符串下标i,已选字符数组chars,左括号数量lc
function backtrace(i, chars, lc) {
// 合法子串,比较长度并填入最终结果
if (!lc && chars.length && chars.length > res[0].length) res = [chars.join('')];
else if (!lc && chars.length && chars.length === res[0].length) res.push(chars.join(''));

// 下标越界,遍历结束
if (i >= s.length - 1) return;

// 遍历所有待选字符
for (let j = i + 1; j < s.length; j++) {
const c = s[j];
// 剪枝:存在无法配对的右括号
if (c === ')' && !lc) continue;
// 剪枝:1、左括号比剩余子串更长;2、已选子串长度加上未遍历子串长度还是小于结果子串的长度
if (lc > s.length - j || chars.length + s.length - j < res[0].length) break;

// 选择当前字符
chars.push(c);
// 递归搜索
backtrace(j, chars, c === '(' ? lc + 1 : (c === ')' ? lc - 1 : lc));
// 撤销选择
chars.pop();
}
}

// 初始状态:字符串下标i为-1,已选字符数组chars为空数组,左括号数量lc为0
backtrace(-1, [], 0);

return [...new Set(res)];
};

4、执行结果

image.png

· 阅读需 5 分钟

1、题干

我们有 n 栋楼,编号从 0 到 n - 1 。每栋楼有若干员工。由于现在是换楼的季节,部分员工想要换一栋楼居住。

给你一个数组 requests ,其中 requests[i] = [fromi, toi] ,表示一个员工请求从编号为 fromi 的楼搬到编号为 toi 的楼。

一开始 所有楼都是满的,所以从请求列表中选出的若干个请求是可行的需要满足 每栋楼员工净变化为 0 。意思是每栋楼 离开 的员工数目 等于 该楼 搬入 的员工数数目。比方说 n = 3 且两个员工要离开楼 0 ,一个员工要离开楼 1 ,一个员工要离开楼 2 ,如果该请求列表可行,应该要有两个员工搬入楼 0 ,一个员工搬入楼 1 ,一个员工搬入楼 2 。

请你从原请求列表中选出若干个请求,使得它们是一个可行的请求列表,并返回所有可行列表中最大请求数目。

 

示例 1:

输入:n = 5, requests = [[0,1],[1,0],[0,1],[1,2],[2,0],[3,4]]
输出:5
解释:请求列表如下:
从楼 0 离开的员工为 x 和 y ,且他们都想要搬到楼 1 。
从楼 1 离开的员工为 a 和 b ,且他们分别想要搬到楼 2 和 0 。
从楼 2 离开的员工为 z ,且他想要搬到楼 0 。
从楼 3 离开的员工为 c ,且他想要搬到楼 4 。
没有员工从楼 4 离开。
我们可以让 x 和 b 交换他们的楼,以满足他们的请求。
我们可以让 y,a 和 z 三人在三栋楼间交换位置,满足他们的要求。
所以最多可以满足 5 个请求。

示例 2:

输入:n = 3, requests = [[0,0],[1,2],[2,1]]
输出:3
解释:请求列表如下:
从楼 0 离开的员工为 x ,且他想要回到原来的楼 0 。
从楼 1 离开的员工为 y ,且他想要搬到楼 2 。
从楼 2 离开的员工为 z ,且他想要搬到楼 1 。
我们可以满足所有的请求。

示例 3:

输入:n = 4, requests = [[0,3],[3,1],[1,2],[2,0]]
输出:4

 

提示:

  • 1 <= n <= 20
  • 1 <= requests.length <= 16
  • requests[i].length == 2
  • 0 <= fromi, toi < n

2、解法1-回溯

回溯枚举 requests 所有子集,如果所有节点的出度和入度都为0则属于可行的请求列表,取所有可行请求列表的最大长度作为返回结果


3、代码

var maximumRequests = function (n, requests) {
let max = 0;
function backtrace(i, path) {
const sums = new Array(n).fill(0);
for (const [f, t] of path) sums[f]--, sums[t]++;
if (sums.every(s => !s)) max = Math.max(max, path.length);

for (let j = i + 1; j < requests.length; j++) {
path.push(requests[j]);
backtrace(j, path);
path.pop();
}
}

for (let i = 0; i < requests.length; i++) backtrace(i, [requests[i]]);

return max;
};

4、执行结果

image.png


5、解法2-BFS

BFS 枚举 requests 所有子集,如果所有节点的出度和入度都为0则属于可行的请求列表,取所有可行请求列表的最大长度作为返回结果


6、代码

var maximumRequests = function (n, requests) {
let max = 0, queue = requests.map((r) => [r]);
while (queue.length) {
const nextQueue = [];
for (let i = 0; i < queue.length; i++) {
const reqs = queue[i], sums = new Array(n).fill(0);

for (const [f, t] of reqs) sums[f]--, sums[t]++;
if (sums.every((s) => !s)) max = Math.max(max, reqs.length);

const idx = requests.indexOf(reqs[reqs.length - 1]);
for (let j = idx + 1; j < requests.length; j++) nextQueue.push([...reqs, requests[j]]);
}
queue = nextQueue;
}
return max;
};

7、执行结果

  • 执行用时: 924 ms
  • 内存消耗: 68 MB

· 阅读需 1 分钟

1、题干

给定一个不含重复数字的整数数组 nums ,返回其 所有可能的全排列 。可以 按任意顺序 返回答案。

 

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

 

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

 

注意:本题与主站 46 题相同:https://leetcode-cn.com/problems/permutations/ 

2、解题思路

BFS每次往组合中添加1个数

3、代码

var permute = function (nums) {
const queue = nums.map(n => [n]);
while (queue[0] && queue[0].length !== nums.length) {
const arr = queue.shift();
for (const n of nums) if (!arr.includes(n)) queue.push([...arr, n]);
}
return queue;
};

· 阅读需 1 分钟

1、题干

给定一个不含重复数字的整数数组 nums ,返回其 所有可能的全排列 。可以 按任意顺序 返回答案。

 

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

 

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

 

注意:本题与主站 46 题相同:https://leetcode-cn.com/problems/permutations/ 

2、解题思路

BFS每次往组合中添加1个数

3、代码

var permute = function (nums) {
const queue = nums.map(n => [n]);
while (queue[0] && queue[0].length !== nums.length) {
const arr = queue.shift();
for (const n of nums) if (!arr.includes(n)) queue.push([...arr, n]);
}
return queue;
};