leetcode-47-Permutations II 搜索-剪枝

来源:互联网 发布:使命召唤ol宏数据 编辑:程序博客网 时间:2024/06/03 18:09

问题

题目:[Permutations II]

思路

上来下来个简单的办法,STL套路。

代码

class Solution {public:    vector<vector<int>> permuteUnique(vector<int>& nums) {        std::vector< std::vector<int> > ret;        std::sort( nums.begin(), nums.end() );        do ret.push_back( nums );        while( std::next_permutation( nums.begin(), nums.end() ) );        return ret;    }};

思路

当然,利用上一题的做法,上来就对位置全排列。每一次到边界的时候放到集合里面去,去重。思路完全可行。但是没有考虑复杂度,因为位置全排列,长度为n的数组,按位置全排列时n!,这个复杂度非常不可接受。上一道能过是因为,就是那么多,所以好的办法。但是这个题目应该存在明显的剪纸的情形可以优化复杂度。

代码1(TLE)

class Solution {public:    vector<vector<int>> permuteUnique(vector<int>& nums) {        std::set< std::vector<int> > ret;        std::vector< int > arr( nums.size(), int() );        std::set<int> visit;        dfs( 0, arr, visit, nums, ret );        std::vector< std::vector<int> > ret1(ret.begin(), ret.end() );        return ret1;    }private:    void dfs( int depth, std::vector<int>& arr, std::set<int>& visit,              const std::vector<int>& nums, std::set< std::vector<int> >& ret ){                  int sz = nums.size();                  for( int i = 0; i < sz; ++i )                  {                      std::set<int> __visit = visit;                        if( __visit.find( i ) == __visit.end() )                        {                            arr[depth] = nums[i];                            __visit.insert( i ); // insert the location of nums[i]                            if( sz-1 == depth )                                ret.insert( arr );                            else                                dfs( depth+1, arr, __visit, nums, ret );                        }                  }              }    };

思路

前面已经说了,上来位置全排列。但是不行,dfs复杂度太大。所以,剪枝。剪枝有两个点需要考虑。

  • 如果同一层次,当前试探元素前面有重复元素,需要剪枝。[1,1,2],因为同一层次如果元素相同,考虑互相交换后的结果,试探的分枝一样。所以,剪枝。
  • 在上面基础之上,剪枝时需要小心一点,如果前面的元素已经出现在上一个层次当中,比如对于第二层的元素,应该在本层的有效元素当中,考虑对重复元素的剪枝。比如[1,1,2],第一层用1展开,第二层,如果只是考虑前面元素是否重复,那么第二个1无法展开,但是第一个1已经出现在上一个层次当中,所以应该避免考虑这些元素。

最后说一个,昨天位置全排列需要小心的一点就是,每层所有元素试探的时候,本质是相互独立的,所以均要使用上一层次的哈希表。

考虑[1,1,1],第一层试探1,第二层试探第二个1,虽然前面出现了1,但是由于第一个1在上一个层次,所以不影响。第二个1展开。还是对于第二层,第三个1,由于第二个1没有在上一层出现过,并且和当前1重复,所以当前试探剪枝。

代码2(剪枝)

class Solution {public:    vector<vector<int>> permuteUnique(vector<int>& nums) {        int sz = nums.size();        std::vector< std::vector<int> > ret;        std::vector< int > arr( sz, int() );        std::set<int> visit;        dfs( 0, arr, visit, nums, ret);        return ret;    }private:    void dfs( int depth, std::vector<int>& arr, std::set<int>& visit,              const std::vector<int>& nums, std::vector< std::vector<int> >& ret){                  int sz = nums.size();                  for( int i = 0; i < sz; ++i )                  {                      std::set<int> __visit = visit;                        int j;                        for( j = 0; j < i; ++j )                        {                            if( __visit.find(j) != __visit.end() ) // j 在上一层出现过,不影响本层的重复                                continue;                            if(  nums[j] == nums[i] )                                break;                        }                        if( j < i )                            continue;                        if( __visit.find( i ) == __visit.end() )                        {                            arr[depth] = nums[i];                            __visit.insert( i ); // insert the location of nums[i]                            if( sz-1 == depth )                                ret.push_back( arr );                            else                                dfs( depth+1, arr, __visit, nums, ret);                        }                  }              }    };
0 0
原创粉丝点击