Permutations leetcode

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].

排列问题,

直观的排列问题如{1,2,3} 当第一次位的1 确定的时候后,需要从2,3 里面进行全排列,然后得到 1,2,3 和,1,3,2。

因此得到一个算法,用一个flags 来记录这个数是否已经被用过。

如果已经选到第n个字符( level ==n) 那就把记录下的路径,加到输出结果里。

如果到level 还没有到字符串长度的时后,

     遍历flags数组,找到第一个没有用过的字符,把这个字符加到中间的结果里,然后在把该字符标记为用过,

      递归选level+1位置上的字符。

    当递归结束的时候,把该字符标记为可用。

//
//排列问题的解法,最基本的肯定是递归
//
    void getpermute(vector<int>& num, vector<vector<int>> &result, vector<int>& v, vector<bool>& flags, int level)
    {
        if(level == num.size())// end of 
        {
            result.push_back(v);
            return;
        }
        else
        {
            for( int k=0; k<num.size(); k++)
            {
                if(flags[k] == true) continue;
                
                v[level]= num[k];
                flags[k] = true;
                getpermute(num, result, v, flags, level+1);
                flags[k] = false;
            }
        }
    }
    
    vector<vector<int> > permute(vector<int> &num) {
        int len = num.size();
        vector<bool> flags(len);
        vector<vector<int>> result;
        vector<int> v(len);
        int level =0;
        
        getpermute(num, result, v, flags, level);
        
        return result;
    }

 

这个题目的变种还可以变成,给定字符集比如 {1,2,3,4} 让你找出所有长度为3的排列。

这个怎么做呢,其实很简单,就在上面的中止条件上改成当flags = targetlength,就中止。

思路还是不变,搞个flags 数组,

当目标排列字符串数组位置level = targetlength的时候就可以把结果输出了。

如果当目标字符串数组位置level 还没有到targetlength时候  

          遍历整个flags的数组,找到第一个没有用过的数

         标记这个数,

         把这个数放到中间结果里         

         递归选level+1位置上的字符。

         当递归结束的时候,把该字符标记为可用。

void getpermute(vector<int>& num, vector<vector<int>> &result, vector<int>& v, vector<bool>& flags, int level, int targetlength)
{
    if (level == targetlength)// end of 
    {
        result.push_back(v);
        return;
    }
    else
    {
        for (int k = 0; k<num.size(); k++)
        {
            if (flags[k] == true) continue;

            v[level]=num[k];
            flags[k] = true;
            getpermute(num, result, v, flags, level + 1, targetlength);
            flags[k] = false;
        }
    }
}

 

另外一种变种是目标集合里面包含重复的元素

一种简单的办法就是消耗空间的set,这样保证题目能做出来。

另外就要考虑如何保持消除重复,直觉关键还是在flags上。

 

BAXYZ

当处理X这个字符的时候,如果X==A而且A这字符已经处理过得情况下,原来的字符串变成了BAAYZ, 表明这个情况已经处理过了。 

   void getpermute(vector<int>& num, vector<vector<int>> &result, vector<int>& v, vector<bool>& flags, int level)
    {
        if(level == num.size())// end of 
        {
            result.push_back(v);
            return;
        }
        else
        {
            for( int k=0; k<num.size(); k++)
            {
                if(flags[k] == true || k!=0 && num[k-1]== num[k]&& flags[k-1]) continue; //当前这个字符和前面的字符一样,并且前面的那个字符已经用过了,
                v[level]= num[k];
                flags[k] = true;
                getpermute(num, result, v, flags, level+1);
                flags[k] = false;
            }
        }
    }
    
    vector<vector<int> > permuteUnique(vector<int> &num) {
        int len = num.size();
        vector<bool> flags(len);
        vector<vector<int>> result;
        vector<int> v(len);
        int level =0;
        sort(num.begin(), num.end());
        getpermute(num, result, v, flags, level);
        
        return result;
    }

 

posted @ 2014-02-10 05:42  来自海边的一片云  阅读(320)  评论(0编辑  收藏  举报