《LeetCode之每日一题》:192.全排列 II
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:192.全排列 II相关的知识,希望对你有一定的参考价值。
题目链接: 全排列 II
有关题目
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
题解
法一:搜索回溯
参考官方题解
回溯三要素:
①有效结果,本题为当前结果的长度等于列表的长度,即为找到了一个有效结果
②回溯范围及答案更新,本题回溯范围为顺序遍历全部,答案更新为used[i]标记之后的内部回溯中产生
curr.push_back(nums[i]);
used[i] = true;
backtrack(ans, nums, idx + 1, curr, used);
curr.pop_back();
used[i] = false;
③减枝
减枝Ⅰ
used[i] 表示当前位置在之前已经被使用,则该位置不能再填入该数字
减枝Ⅱ
!used[i - 1]上一个位置刚刚被撤销选择,又碰到一个相同的元素,会出现跟上一步骤相同的排列,则该位置不能再填入该数字
class Solution {
public:
void backtrack(vector<vector<int>> &ans, vector<int> &nums, int idx, vector<int> &curr, vector<bool> &used)
{
if (idx == (int)nums.size())
{
ans.push_back(curr);
return ;
}
for (int i = 0; i < (int)nums.size(); i++)
{
//i > 0为了保证i - 1有效
//减枝①
//used[i] 表示当前位置在之前已经被使用
//减枝②
//!used[i - 1]上一个位置刚刚被撤销选择,又碰到一个相同的元素,会出现跟上一步骤相同的排列
if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]))
continue;
curr.push_back(nums[i]);
used[i] = true;
backtrack(ans, nums, idx + 1, curr, used);
curr.pop_back();
used[i] = false;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> ans;
vector<bool> used(n);
vector<int> curr;
sort(nums.begin(), nums.end());//排序,为了减枝方便
backtrack(ans, nums, 0, curr, used);
return ans;
}
};
以上是关于《LeetCode之每日一题》:192.全排列 II的主要内容,如果未能解决你的问题,请参考以下文章