题目: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].
思路一(无重复元素):这是通过交换得到的全排列。
class Solution { public: vector<vector<int> > permute(vector<int> &num) { vector<vector<int> > v; ProduceArray(num, 0, v); return v; } void ProduceArray(vector<int> data, int index, vector<vector<int> > &v) { int n = data.size(); if(index == n) { v.push_back(data); return; } for(int i=index;i < n;i++) { swap(data[i], data[index]); ProduceArray(data, index+1, v); swap(data[i], data[index]); } } };注意: 这种方法的缺点是 如果序列中有重复元素,得到的排列也是有重复的。
思路二:第一种方法的思路是交换,第二种方法的思路就是插入。首先拿出原序列的第一个元素,然后将其插入到剩余序列中,有n种插入方法(得到的序列个数是原来的n倍)。递归地,剩余序列也可以这么做而得到。这也可以看作是一种分治策略,即把规模为N的原问题分解为规模为1的问题和规模为N的问题。
代码:
#include <iostream> #include <string> #include <vector> using namespace std; string insertCharAt(const string &word, char c, int i) { if(i<0 || i > word.size()) return word; string left = word.substr(0, i); string right = word.substr(i); return left + c + right; } vector<string> genPermutation(const string &s) { vector<string> re; if(s.size() == 1) { re.push_back(s); return re; } char first = s[0]; string rest = s.substr(1); vector<string> restwords = genPermutation(rest); vector<string>::iterator it = restwords.begin(); for( ;it != restwords.end();it++) { for(int i=0;i<=(*it).size();i++) { re.push_back(insertCharAt((*it), first, i)); } } return re; } int main(int argc, const char * argv[]) { string s = "abc"; vector<string> permutation = genPermutation(s); cout<<permutation.size()<<endl; vector<string>::iterator it = permutation.begin(); for(; it != permutation.end();it++) cout<<(*it)<<endl; return 0; }
思路三(有重复元素):先利用hash给每种不同的数做计数统计,然后用backtrack方法。需要辅助空间。
class Solution { public: vector<vector<int> > permuteUnique(vector<int> &num) { vector<vector<int> > v; int n = num.size(); if(n == 0) return v; map<int, int> m; for(int i=0;i<n;i++) if(m.find(num[i]) == m.end()) m[num[i]] = 1; else m[num[i]]++; vector<int> now; backtrack(m, v, num, n, now, 0); return v; } void backtrack(map<int, int> &m, vector<vector<int> > &v, vector<int> &num, int n, vector<int> now, int idx) { if(idx == n) { v.push_back(now); return; } map<int, int>::iterator it = m.begin(); for(;it != m.end(); it++) { if((*it).second > 0) { (*it).second--; now.push_back((*it).first); backtrack(m, v, num, n, now, idx+1); (*it).second++; now.pop_back(); } } } };