全排列
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]
.
题目意思:
给定一个集合,求全排列。
解题思路:
一般的话,有两种思路可以考虑。递归和DFS遍历树。
这里我只用了递归的方法,关于怎么建一棵树然后DFS,可以参考 这里。
这对于练习对递归的理解真是个不错的题目。
以[1,2,3]举例,可以用纸笔画一画,分别以1,2,3为根,画出三棵树来,然后由根到每一个节点就对应着一个排列。
首先最外层肯定要有一个for循环来一次遍历这里面的元素决定出根节点,然后在循环中递归。
其中,有两点需要注意的:
要设置一个bool型的visited数组,大小和num一样大,来标记num中对应的元素是否已经访问过了,对于还没有访问过的,我们才可以把它加到element里来。这样可以避免在树的不同层出现同一个数。
在element已经完成了一次排列后,对element进行pop_back(),然后将pop出来的数对应的visited设置为true,表示它现在可以被访问了。举例来说,当element中已经有了[1,2,3]并且添加到result里后,进行一个pop_back()剩下[1,2]并将visited[2]置为true,然后跳到上一层调用,再pop_back()剩下[1]并将visited[1]置为true,此时for循环i++,此时visited[2]为true,即向element里添加num[2],element变成[1,3],接着再调用递归,在下一层因为visited[0]为false,visited[1]为true,element将添加num[1]变成[1,3,2]。
对递归不熟的朋友,可以一边对着代码,一边用笔画一下几个树,过几遍就OK拉!
代码如下:
1 #include <vector> 2 #include <iostream> 3 using namespace std; 4 5 class Solution { 6 public: 7 vector<vector<int> > permute(vector<int> &num) { 8 vector<vector<int>> result; 9 vector<int> element; 10 11 int len = num.size(); 12 bool *visited = new bool[len]; 13 memset(visited,false,len); 14 15 helper(num,result,element,visited); 16 return result; 17 } 18 19 private: 20 void helper(vector<int> &num,vector<vector<int>> &result,vector<int> &element,bool *visited){ 21 if(element.size() == num.size()){ 22 //element中元素和num中元素一样多,说明得到了一个全排列,放进result里 23 result.push_back(element); 24 return ; 25 } 26 27 for(int i = 0; i < num.size(); i++){ 28 if(!visited[i]){ 29 visited[i] = true; 30 element.push_back(num[i]); 31 helper(num,result,element,visited); 32 33 element.pop_back(); 34 visited[i] = false; 35 } 36 } 37 } 38 }; 39 40 int main(){ 41 Solution s; 42 vector<int> num; 43 num.push_back(1); 44 num.push_back(2); 45 num.push_back(3); 46 s.permute(num); 47 }