【LeetCode】47. 全排列 II Permutations II(C++)


题目来源:https://leetcode-cn.com/problems/permutations-ii/

题目描述

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10

题目大意

  • 本题与https://leetcode-cn.com/problems/permutations/类似,解题方法均为回溯法,不过本题需要对回溯法进行一个剪枝操作
  • 对于示例1,如果全排列可重复的话,会有3!中情况,但是因为有重复的元素1,所以将重复的元素入排列的情况排除掉,如果当前的元素nums[i]与上一个元素nums[i-1]重复,且上一个元素已经在排列当中(used[i-1]==true)所以就将这个元素的递归栈返回到当前要排列元素(结点)的父节点,然后父递归栈循环i++,再将后面的元素入排列考虑

回溯法介绍

  • 回溯法是一种算法思想,而递归是一种编程方法,回溯法可以用递归来实现。
  • 回溯法的整体思路是:搜索每一条路,每次回溯是对具体的一条路径而言的。对当前搜索路径下的的未探索区域进行搜索,则可能有两种情况:
class Solution {
    
    
public:
    vector<vector<int>> ret;
    vector<int> ans;
    vector<bool> used;
    int n;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
    
    
        n = nums.size();
        used.assign(n, false);
        sort(nums.begin(), nums.end());
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int depth){
    
    
        if(depth == n){
    
    
            ret.push_back(ans);
            return;
        }
        for(int i = 0 ; i < n ; ++i){
    
    
            if(!used[i]){
    
    
                if(!ans.empty() && i - 1 >= 0 && nums[i - 1] == nums[i] && used[i - 1] == true)
                    return;
                used[i] = true;
                ans.push_back(nums[i]);
                dfs(nums, depth + 1);
                used[i] = false;
                ans.pop_back();
            }

        }
    }
};

复杂度分析

  • 时间复杂度:O(n*2^n)。n为数组的长度,共有2^n个情况,需要O(n)时间来创建
  • 空间复杂度:O(n)。递归栈空间为(n)

猜你喜欢

转载自blog.csdn.net/lr_shadow/article/details/114521077