这道题是求一个指定序列的全排列,使用的算法思想是非常基本的深度优先搜索(dfs)+回溯(backtrack)。因为解法非常典型并且具有代表性,所以在此加以总结。
深度优先搜索意味着一次搜索将会进行到搜索空间的最深处才停止,而回溯则意味着解状态的回退,也就是上一步深度搜索动作的对应解除。在解决问题的代码中,Current表示当前已经生成的排列,Used数组是标明某个数字是否已经使用的标志数组。核心函数dfs的代码如下:
void dfs( vector<vector<int>>& Result,
vector<int>& Current, /*current permutation*/
vector<int>& nums, /*number array*/
bool* Used /*flag array indicating whether has been used*/
)
{
/*end of dfs*/
if(Current.size() == nums.size())
Result.push_back(Current);
for(int i = 0 ; i < nums.size() ; ++i)
{
/*if the i-th element has not been used*/
if(!Used[i])
{
/*search deeper*/
Current.push_back(nums[i]);
Used[i] = true; /*modify the flag*/
/*search deeper into next layer*/
dfs(Result, Current, nums, Used);
/*backtrack*/
Current.pop_back();
Used[i] = false;
}
}
}
从上述代码中可以看到,向更深的层次搜索意味着两个动作:
1.将没有使用过的数字加入Current
2.将使用过的数字标记为true(已经使用)
/*search deeper*/
Current.push_back(nums[i]);
Used[i] = true; /*modify the flag*/
回溯则是将上述的两个步骤逐步撤销:
/*backtrack*/
Current.pop_back();
Used[i] = false;
这道题完整的解决代码如下:
void dfs(vector<vector<int>>& Result, vector<int>& Current, vector<int>& nums, bool* Used)
{
/*end of dfs*/
if(Current.size() == nums.size())
Result.push_back(Current);
for(int i = 0 ; i < nums.size() ; ++i)
{
/*the i-th element has not been used*/
if(!Used[i])
{
Current.push_back(nums[i]);
Used[i] = true; /*modify the flag*/
/*search deeper into next layer*/
dfs(Result, Current, nums, Used);
/*back track*/
Current.pop_back();
Used[i] = false;
}
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
/*apply for a new array indicating whether te number has been used*/
bool* Used = new bool[nums.size()];
/*initialize the 'Used' array*/
for(int i = 0 ; i < nums.size() ; ++i)
Used[i]= false;
/*the final result*/
vector<vector<int>> Result;
/*current permutation*/
vector<int> Current;
dfs(Result, Current, nums, Used);
return Result;
}