leetcode 47.全排列II

leetcode 47.全排列II

题干

给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]

题解

经典回溯算法
* 核心问题在重复数字序列的处理,需要在判断前加上i>0的判断,否则当i==0时就会出现nums[-1]的越界情况
* 还有一个核心在A代码块,推入一个答案后进行递归,在递归语句后将这个元素取出,对下一个元素进行递归
* 将ans设为函数引用参数可以提高效率,即将vector<vector>& ans作为dfs的参数传入
* (并不)其实这个解法的去重是不完全的,这个解法只能在单支递归中避免重复数据带来的答案重复,实际上在不同分支的递归中仍然可能出现重复结果,而且nums中的重复元素越多,这种重复性就越高
* 上述想法是错的,实际去重是能避免重复结果的

class Solution {
    
    
public:
    vector<vector<int>> ans;
    vector<int> vis;//全局自动置0
    void dfs(int now,vector<int> nums,vector<int>& singleArray){
    
    
        if(now==nums.size())
        {
    
    
            ans.push_back(singleArray);
            return;
        }
        for(int i=0;i<nums.size();i++)
        {
    
    
            if(vis[i]==1 || (i>0 && nums[i]==nums[i-1] && vis[i-1]==0))//如果插入过了或者这个数字不是重复数字序列未插入过的第一个
                continue;
            singleArray.push_back(nums[i]);			//***************
            vis[i] = 1;								//
            dfs(now+1,nums,singleArray);			//		A
            vis[i] = 0;								//
            singleArray.pop_back();					//***************
        }                
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
    
    
        sort(nums.begin(),nums.end());
        vis.resize(nums.size());
        vector<int> singleArray;
        dfs(0,nums,singleArray);
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43662405/article/details/108684633