一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
题目列表
Leetcode 46
题目内容
给定一个不含重复数字的数组
nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
关键词:: 不重复、任意顺序返回、 求全排序
Leetcode 47
题目描述 给定一个可包含重复数字的序列
nums
,按任意顺序 返回所有不重复的全排列。
77题组合
题目详情: 给定两个整数
n
和k
,返回范围[1, n]
中所有可能的k
个数的组合。你可以按 任何顺序 返回答案。
我们可以观察到这几个题目的内容,都是相关与排列组的,排列组合的基本思想是深度优先搜索+回溯。如果题目有特殊的需求的话我们还可以进行剪枝。 我们最简单的思想就是,首先选择其中一个数字,然后再从剩下的数字之中选择一个数字,以此类推,当我们把所有数字选择 完了的时候这就是我们需要的一个答案,然后我们进行回溯操作,但是必要是的我们需要标记数组中每一个元素的使用情况,所以我们需要用一个数组来记录。 下面 我们来分析下47题的代码
主体思路:
- dfs全排列结果 (其中包含有重复的答案)
- 对dfs的结果进行pop——repeat
//创建一个深度优先搜索的函数
void dfs(vector<vector<int>>& ans,vector<int>& tmp,vector<int>& nums,vector<bool> &on_use,int k){
//结束条件为 我们已经选择了所有的元素了
if(tmp.size() == k){
//把这个答案放入 我们的ans中 (ans是记录答案的二维数组)
ans.push_back(tmp);
return;
}
//递归
for(int i = 0;i<nums.size();i++){
if(!on_use[i]){
on_use[i] = true;
tmp.push_back(nums[i]);
dfs(ans,tmp,nums,on_use,k);
tmp.pop_back();
on_use[i] = false;
}
}
}
void pop_repeat(vector<vector<int>>& ans,vector<vector<int>>& ans2,int nums_size){
//去除重复的元素
for(int i = 0;i<ans.size();i++){
int flag=0,count=0;
for(int j = i+1;j<ans.size();j++){
flag = 0;
//统计是否重复 flag == nums_size 时候重复
for(int k = 0;k<nums_size;k++){
if(ans[i][k] == ans[j][k]){
flag +=1;
}else{
break;
}
}
if(flag == nums_size){
count+=1;
break;
}
}
if(count == 0){
ans2.push_back(ans[i]);
}
}
}
//主函数
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool> on_use(nums.size(),false); //标记元素的使用情况
vector<int> tmp; //临时数组 储存每一个元素
vector<vector<int>> ans; // 包含有 重复答案的数组
vector<vector<int>> ans2; //把 ans中 不重复的元素存到 ans2里边儿 做最终答案
dfs(ans,tmp,nums,on_use,nums.size());
pop_repeat(ans,ans2,nums.size());
return ans2;
}