//给定一个可包含重复数字的序列 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 
// 
// Related Topics 回溯算法 
// 👍 609 👎 0

/*
* 47 全排列 II
* 2021-02-28 13:16:50
* @author oxygenbytes
*/ 
#include "leetcode.h" 
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public:
    vector<vector<int>> ans;
    vector<int> path;
    vector<bool> vis;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vis = vector<bool>(n, false);

        dfs(nums, 0);
        return ans;
    }

    void dfs(const vector<int>& nums, int cur){
        if(cur == nums.size()){
            ans.push_back(path);
            return ;
        }
// 例如[1 2 2‘]可能出现[1 2 2'] 和[1 2‘ 2] 的情况 如果“存在前一个相同元素” 且“未被使用过”, 当现有排列是[1 2']时
// 原来的数组[1 2 2‘]中2’存在前一个元素2与其相同, 且此时2未被访问过,跳过。[1 2 2']的排列先于[1 2' 2]存在,因此可以去除。
        for(int i = 0;i < nums.size();i++){
            if(!vis[i]){

                vis[i] = true;
                path.push_back(nums[i]);
                dfs(nums, cur + 1);
                path.pop_back();
                vis[i] = false;
                // [2,2',3] if cur(0) == 2, then skip cur(1)
                while(i + 1< nums.size() && nums[i] == nums[i+1]) i++; // here is while
            }
        }
    }
};
//leetcode submit region end(Prohibit modification and deletion)