LeetCode——46. 全排列

182 篇文章 0 订阅
8 篇文章 0 订阅

回溯算法全排列详细解析参考:回溯

题目描述:

给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:

[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

java代码如下:

class Solution {
    public static List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> ans = new LinkedList<>();
        LinkedList<Integer> t = new LinkedList<>();
        bt(ans, nums, t);
        return ans;
    }

    public static void bt(List<List<Integer>> ans, int[] nums, LinkedList<Integer> t) {
        if (t.size() == nums.length) {
            //ans.add(t)是不对的,返回的全是空列表,原因是变量t所指向的列表,在深度优先遍历的过程中只有一份,深度优先遍历完成以后,回到了根结点,成为空列表。
            //在Java中,参数传递是 值传递,对象类型变量在传参的过程中,复制的是变量的地址。这些地址被添加到ans变量,但实际上指向的是同一块内存地址,因此我们会看到空的列表对象。解决的方法很简单,在 res.add(t); 这里做一次拷贝即可。
            ans.add(new LinkedList<>(t));
            return;
        }
        for (int num : nums) {
            if (t.contains(num)) {
                continue;
            }
            t.add(num);
            bt(ans, nums, t);
            t.removeLast();
        }
    }
}
class Solution {
    public static List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> ans = new LinkedList<>();
        LinkedList<Integer> t = new LinkedList<>();
        boolean[] used = new boolean[nums.length];
        bt(ans, nums, t, used, 0);
        return ans;
    }

    public static void bt(List<List<Integer>> ans, int[] nums, LinkedList<Integer> t, boolean[] used, int depth) {
        if (depth == nums.length) {
            ans.add(new LinkedList<>(t));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) {
                continue;
            }
            t.add(nums[i]);
            used[i] = true;
            bt(ans, nums, t, used, depth + 1);
            used[i] = false;
            t.removeLast();
        }
    }
}

c++代码如下:(可做模板使用)

class Solution {
public:
    vector<vector<int> >res;
    vector<vector<int>> permute(vector<int>& nums) {
        vector<int>path;
        vector<bool>used(nums.size(),false);
        tb(used,path,nums);
        return res;
    }
    void tb(vector<bool>&used,vector<int>&path,vector<int>nums){
        if(path.size()==nums.size()){
            res.push_back(path);
            return ;
        }
        for(int i=0;i<nums.size();i++){
            if(used[i]){
                continue;
            }
            path.push_back(nums[i]);
            used[i]=true;
            tb(used,path,nums);
            used[i]=false;
            path.pop_back();
        }
    }
};

执行结果:
在这里插入图片描述

全排列Ⅱ

给定一个可包含重复数字的序列 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

class Solution {
    boolean[] vis;

    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        List<Integer> perm = new ArrayList<Integer>();
        vis = new boolean[nums.length];
        Arrays.sort(nums);
        backtrack(nums, ans, perm);
        return ans;
    }

    public void backtrack(int[] nums, List<List<Integer>> ans, List<Integer> perm) {
        if (perm.size() == nums.length) {
            ans.add(new ArrayList<Integer>(perm));
            return;
        }
        for (int i = 0; i < nums.length; ++i) {
         	//true表示用过了
            //剪枝条件,i>0,是为了保证nums[i-1]有意义
            //vis[i-1]是因为nums[i-1]在回退的过程中刚刚被撤销了选择
            if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1])) {
                continue;
            }
            perm.add(nums[i]);
            vis[i] = true;
            backtrack(nums, ans, perm);
            vis[i] = false;
            perm.remove(perm.size() - 1);
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值