演示回溯法最常用的例子应该就是
全排列、组合和、回文分区了(Subsets, Permutations, Combination Sum, Palindrome Partioning)
Combination Sum
Palindrome Partioning
Subsets
以上是相应的Leetcode题目地址。
就以Permutation为例
Given a collection of distinct 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],
[3,2,1]
]
意思就是给一系列不重复的数字nums,返回他们的全排列,现在暂时不考虑重复问题
思路就是 先固定第一个数,然后以此数为结点依次往下,然而固定第二个数,当到达叶子时(即长度为nums的长度),就将结果保存,然后往回走,挨个pop_back,其实就是深度优先搜索,看代码就可以明白了。
class Solution
{
vector<vector<int>> result;//放外面纯粹是懒
public:
void helper(vector<int>& vec, vector<bool>& visited, vector<int>& cur)
{
if (cur.size() == vec.size())
{
result.push_back(cur); //cur的长度等于vec长度显然就到达叶子节点了
return;
}
for (int i = 0; i < vec.size(); ++i)
{
if (visited[i] == false) //visited用于固定数字
{
visited[i] = true;
cur.push_back(vec[i]);
helper(vec, visited, cur); //到达1 2 3 后
cur.pop_back(); //此处将3弹出,之后的同理
visited[i] = false;
}
}
}
vector<vector<int>> permute(vector<int>& nums)
{
if (nums.size() == 0)
return result;
vector<bool> visited(nums.size(), false);
vector<int> cur;
helper(nums, visited, cur);
return result;
}
};
其进阶版 就 存在 重复的数duplicate
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
大致的框架还是没变的,但要考虑到跳过重复元素的问题
首先将数进行排序,方便进行重复元素判断
当判断第i个元素是否是重复的元素时,判断i-1是否被固定且i和i-1元素是否相等,若其前一个元素与之相等且未被使用过,那么显然就跳过当前元素,重复元素的使用应当是有序的。
然后和上面版本一样判断i元素是否被固定
class Solution {
public:
vector<vector<int>>result;
vector<vector<int>> permuteUnique(vector<int>& nums) {
if(nums.size()==0)
return result;
sort(nums.begin(),nums.end());
vector<int>cur;
vector<bool>used(nums.size(),false);
backTrack(nums,cur,used);
return result;
}
void backTrack(vector<int>&nums,vector<int>&cur,vector<bool>&used){
if(cur.size()==nums.size())
{
result.push_back(cur);
return;
}
for(int i = 0;i<nums.size();++i){
if(used[i]||i>0&&!used[i-1]&&nums[i]==nums[i-1])//多出来的就这部分,判断是否重复且前一个元素未使用
continue;
used[i] = true;
cur.push_back(nums[i]);
backTrack(nums,cur,used);
cur.pop_back();
used[i] = false;
}
}
};
其他题目都大同小异了,都有一个一个基本的框架,然后根据题目填就是了