zhizhizhiyuan

Permutations II 再分析

  记得第一遍做这题的时候其实是没什么思路的,但是第二次的时候,我已经有"结果空间树"的概念了。这时候再看https://oj.leetcode.com/problems/permutations-ii/,觉得那样理解未免过于繁,因此重新写下新的思路。以前的文章总是花了时间写,删了可惜,且留着吧。(废话太多了)。

  怎么理解结果空间树?当我们用dfs去寻找结果的时候,实际上是构造了一棵树。我们通常会有如下的代码结构:

  

    void dfs()
    {
        if(expression1)
            do something
        for(int i=0;i<N;i++)
        {
            if(expression2)
                do something
            dfs();
        }
    }

  expression1通常是终止条件。expression2通常是剪枝条件。

  以本题为例,我最终代码是:

class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int> > permuteUnique(vector<int> &num) {
        sort(num.begin(),num.end());
        bool *visits=new bool[num.size()];
        memset(visits,0,sizeof(bool)*num.size());
        vector<int> intermediate;
        dfs(num,intermediate,visits);
        return res;
    }

    void dfs(vector<int>& num,vector<int> &intermediate, bool* visits)
    {
        if(intermediate.size()==num.size())
            res.push_back(intermediate);
        for(int i=0;i<num.size();i++)
        {
            if(visits[i]||(i>0&&num[i]==num[i-1]&&!visits[i-1]))
                continue;
            visits[i]=true;
            intermediate.push_back(num[i]);
            dfs(num,intermediate,visits);
            intermediate.pop_back();
            visits[i]=false;
        }
    }
};

  假设输入如下:[1,1,1,1,2],则树形状如下:

  

 

  红色叉的部分表示剪枝。从上述图来看,或者称为森林还恰当一些,先不管这个。这里关键要理解一点,如何去重?比如第三层的后面两个1是如何去掉的?关键的代码在于这里:

  

i>0&&num[i]==num[i-1]&&!visits[i-1]

 也就是说,要满足以下两个条件:1. 与前一个相等;2. 前一个没有被访问。这样就能保证相同的元素按顺序每层只访问一个。

 说白了,实在没什么高难度的东西。

posted on 2014-07-03 00:07  zhizhizhiyuan  阅读(686)  评论(0编辑  收藏  举报

导航