leetcode 47. 全排列 II 思考分析

80 阅读1分钟

题目

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
在这里插入图片描述
在这里插入图片描述

思考分析以及代码

这一题和前面的做过的两个题目有所关联:
leetcode 46. 全排列 思考分析
再加上leetcode 491. 递增子序列 思考分析类似的去重操作。
先画出解空间树的图:
红色部分才是真正意义上的去重:值相同的跳过。
蓝色部分指的是我们用过的元素不能再用了。在组合问题中由于for循环进入下一层是i+1,所以本身就将用过的元素排除了。然而在排列问题中,我们可能要用到序号靠前且没有使用过的元素,所以需要通过限制去除。
在这里插入图片描述
这里的“去重”我用到了两个数组:

vector<bool> used;
int usedArray[21]={0}; //这里使用数组来进行去重操作。

used存放的是树深度上的元素是否“用过”的信息,用过的元素将不会再用。
usedArray存放的是
树这一层
上的元素是否是重复的元素,重复的元素将不会再用。
所以used是全局变量,usedArray是本层的局部变量。
下面是代码:

class Solution {
public:
    vector<vector<int>> result;
    vector<int> res;
    vector<bool> used;
    void backtracking(vector<int>& nums)
    {
        //如果res元素个数和nums一样多说明一个排列已经完成
        if(res.size() == nums.size())
        {
            result.push_back(res);
            return;
        }
        int usedArray[21]={0}; //这里使用数组来进行去重操作。
        for(int i=0;i<nums.size();i++)
        {
            //used存放的是树深度上的元素是否“用过”的信息,用过的元素将不会再用。
            //usedArray存放的是树这一层上的元素是否是重复的元素,重复的元素将不会再用
            //元素可以是重复但没有用过。
            if(used[i] == false && usedArray[nums[i]+10] ==0)
            {
                usedArray[nums[i]+10] =1;
                //处理结点;
                used[i]=true;
                res.push_back(nums[i]);
                //递归,探索下一层
                backtracking(nums);		//递归
                //回溯,撤销处理结果
                res.pop_back();
                used[i]=false;
            }
            //如果这个元素已经用过了,不做处理
        }
        return;
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
       result.clear();
        res.clear();
        //装载used数组
        for(int i=0;i<nums.size();i++)  used.push_back(false);
        //开始回溯
        backtracking(nums);
        return result;
    }
};

剑指 Offer 38. 字符串的排列

leetcode-cn.com/problems/zi…
这一题类似。