谈算法-排列组合-47-46-77

105 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。

题目列表

Leetcode 46


题目内容

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

image.png

关键词:: 不重复、任意顺序返回、 求全排序

Leetcode 47


题目描述 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 image.png

77题组合

题目详情: 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。

image.png

我们可以观察到这几个题目的内容,都是相关与排列组的,排列组合的基本思想是深度优先搜索+回溯。如果题目有特殊的需求的话我们还可以进行剪枝。 我们最简单的思想就是,首先选择其中一个数字,然后再从剩下的数字之中选择一个数字,以此类推,当我们把所有数字选择 完了的时候这就是我们需要的一个答案,然后我们进行回溯操作,但是必要是的我们需要标记数组中每一个元素的使用情况,所以我们需要用一个数组来记录。 下面 我们来分析下47题的代码

主体思路:

  1. dfs全排列结果 (其中包含有重复的答案)
  2. 对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;
    }