深度优先搜索DFS + 剪枝 | 回溯:力扣47. 全排列 II

1、题目描述:

深度优先搜索DFS + 剪枝 | 回溯:力扣47. 全排列 II_第1张图片

2、题解:

数据结构和算法:从0到1系列 回溯小专题
深度优先搜索DFS | 回溯算法:力扣46. 全排列

result = []
def backtrack(选择列表,路径):
    if 满足结束条件:
        result.add(路径)
        return
    for 选择 in 选择列表:
        做选择
        backtrack(选择列表,路径)
        撤销选择

# 做选择
将该选择从选择列表移除
路径.add(选择)

# 撤销选择
路径.remove(选择)
将该选择再加入选择列表

解决一个回溯问题,实际上就是一个决策树的遍历过程:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。

当然本题在for循环里剪枝,画一个多叉树,可以发现,在多叉树最开始的分支里,如果遇到相同的数,就剪枝,当然之后的每个分支也是一样,如果在同一层遇到相同的开始,就剪枝。

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        #回溯
        res = []
        visited = [False for _ in range(len(nums))]
        def backtrack(nums,path,visited):
            if len(path) == len(nums):
                if path not in res:
                    res.append(path[:])
                return 
            for i in range(len(nums)):
                if not visited[i]:
                    if i > 0 and nums[i] == nums[i-1] and not visited[i-1]: #剪枝
                        continue
                    path.append(nums[i])
                    visited[i] = True
                    backtrack(nums,path,visited)
                    visited[i] = False
                    path.pop()
        backtrack(nums,[],visited)
        return res

C++实现:

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        // 回溯
        vector<vector<int>> res;
        vector<int> path;
        int n = nums.size();
        vector<int> visited(n);
        sort(nums.begin(),nums.end());
        backtrack(nums,path,visited,res);
        return res;
    }
    void backtrack(vector<int>& nums,vector<int>& path,vector<int>& visited,vector<vector<int>>& res){
        if (nums.size() == path.size()){
            res.push_back(path);
            return;
        }
        for (int i=0;i < nums.size();i++){
            if (!visited[i]){
                if (i > 0 && nums[i] == nums[i-1] && !visited[i-1]){
                    continue;
                }
                path.push_back(nums[i]);
                visited[i] = 1;
                backtrack(nums,path,visited,res);
                visited[i] = 0;
                path.pop_back();
            }
        }
    }
};

3、复杂度分析:

在这里插入图片描述

你可能感兴趣的:(LeetCode高频面试题)