1、题目描述:
2、题解:
回溯算法框架:
result = []
def backtrack(选择列表,路径):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(选择列表,路径)
撤销选择
# 做选择
将该选择从选择列表移除
路径.add(选择)
# 撤销选择
路径.remove(选择)
将该选择再加入选择列表
解决一个回溯问题,实际上就是一个决策树的遍历过程:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
可以把「路径」和「选择」列表作为决策树上每个节点的属性
框架的解释:
实现方法1:
Python实现:
class Solution:
def permute(self, nums) :
res = []
def backtrack(nums,temp):
if len(temp) == len(nums):
res.append(temp)
# print(res)
# print(temp)
return
for i in range(len(nums)):
if nums[i] in temp:
continue
# temp.append(nums[i])
backtrack(nums,temp + [nums[i]] )
# temp.remove(nums[i])
backtrack(nums,[])
return res
或者,可以套模板:
class Solution:
def permute(self, nums) :
res = []
def backtrack(nums,path): #path路径,nums为选择列表
if len(path) == len(nums): #结束条件
res.append(path[:])
return
for i in range(len(nums)):#在选择列表中做选择
if nums[i] in path: #剪枝,也就是路径中不能出现重复元素
continue
path.append(nums[i]) #选择
backtrack(nums,path) #向下选择
path.pop() #撤销选择
backtrack(nums,[])
return res
或者:
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
#路径记录在temp中
def backtrack(nums, temp):
if not nums:
res.append(temp)
return
for i in range(len(nums)):
backtrack(nums[:i] + nums[i+1:], temp + [nums[i]])
backtrack(nums, [])
return res
C++实现:
如何快速判断数组中是否存在某值:C++的find()
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
//回溯
vector<vector<int>> res;
vector<int> path;
backtrack(path,nums,res);
return res;
}
void backtrack(vector<int> path,vector<int>& nums,vector<vector<int>>& res){
if (path.size() == nums.size()){
res.push_back(path);
return;
}
for (int i=0;i < nums.size();i++){
if (find(path.begin(),path.end(),nums[i]) != path.end()){
continue;
}
path.push_back(nums[i]);
backtrack(path,nums,res);
path.pop_back();
}
}
};
实现方法2:
当然上面的代码实现,没有完全按照算法思路来做,下面提供另一个版本的实现。
Python实现:
class Solution:
def permute(self, nums) :
#回溯
res = []
visited = [True for _ in range(len(nums))]
def backtrack(nums,path,visited):
if len(path) == len(nums):
res.append(path[:])
return
for i in range(len(nums)):
if visited[i]:
path.append(nums[i])
visited[i] = False
backtrack(nums,path,visited)
visited[i] = True
path.pop()
backtrack(nums,[],visited)
return res
C++实现:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
//回溯
vector<vector<int>> res;
vector<int> path;
vector<int> visited(nums.size(),true);
backtrack(path,nums,res,visited);
return res;
}
void backtrack(vector<int> path,vector<int>& nums,vector<vector<int>>& res,vector<int>& visited){
if (path.size() == nums.size()){
res.push_back(path);
return;
}
for (int i=0;i < nums.size();i++){
if (visited[i]){
path.push_back(nums[i]);
visited[i] = false;
backtrack(path,nums,res,visited);
visited[i] = true;
path.pop_back();
}
}
}
};
3、复杂度分析:
时间复杂度:O(N*N!)
空间复杂度:O(N)