小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
大家好今天给大家分享下一道 LeetCode 中等难度 的题目[47. 全排列 II]
题目
给定一个可包含重复数字的序列
nums,按任意顺序 返回所有不重复的全排列。
分析
1.列出所有的元素的组合,但是数组中的每个元素只能使用一次
2.数组中包含了重复的元素
3.返回一个二维数组
解法
1.递归
2.暴力
解法一:递归
思路
1.给nums排序 方便去重
2.递归
1.终止条件 生成的数组arr的长度等于nums的长度时,arr就是答案之一 放入res中
2.递归的参数中添加usedArr来记录使用过的数组index
3.有2种情况会直接跳过当前的迭代
1.usedArr中已经保持了当前Index的记录
2.当前的index 和之前的index-1的数相同
4.记录使用过的index到usedArr中
5.arr中添加新元素 继续递归
3.返回res答案集合
*/
var permuteUnique = function (nums) {
const res = [];
nums.sort((a, b) => a - b);
function reucr(arr, usedArr) {
if (arr.length === nums.length) {
res.push(arr);
return;
}
for (let i = 0; i < nums.length; i++) {
if (usedArr.includes(i)) {
continue;
}
if (i > 0 && nums[i] === nums[i - 1] && !usedArr.includes(i - 1)) {
continue;
}
const element = nums[i];
const newArr = [...usedArr, i];
reucr([...arr, element], newArr);
}
}
reucr([], []);
return res;
};
/* 复杂度
时间 O(!n)
空间 O(!n*!n)
*/
解法二:暴力
思路
1.生成所有的结果
2.去重复的值
3.去除不合法的值
*/
var permuteUnique = function (nums) {
const res = [];
// 生成所有的结果
function recur(arr) {
if (arr.length === nums.length) {
res.push(arr);
return;
}
for (const num of nums) {
recur([...arr, num]);
}
}
recur([]);
// 去除重复值
function removeDuplicate(arr) {
const seen = new Set();
const res = [];
for (const num of arr) {
const str = num.join(",");
if (!seen.has(str)) {
res.push(num);
seen.add(str);
}
}
return res;
}
// 去除不合法的值
function valid(item, nums) {
const newArr = [...nums];
const newItem = [...item];
return newItem.sort().join("") === newArr.sort().join("");
}
return removeDuplicate(res).filter((item) => valid(item, nums));
};
/* 复杂度
时间 O(n^n)
空间 O(n)
*/
总结
今天这道题是主要是练习递归的方式来处理生成类再结合去重来实现 全排列的所有可能
大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢
大家如果对“TS”感兴趣的可以看看我的专栏 (TypeScript常用知识),感谢大家的支持
文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com
\