全排列[回溯] 力扣Top46全排列1(不重复数字的全排列) 力扣Top47全排列2(重复数字的全排列)

全排列[回溯]

力扣top46 全排列1

题目:

给定一个不含重复数字的数组 nums,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

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

1 <= nums.length <= 6

-10 <= nums[i] <= 10

nums 中的所有整数 互不相同

分析

本题可以使用回溯将所有可能得排列情况记录。

  1. 将当前数组分为左右两部分,左为已经选择并排列的部分,右为还没有选择排列的部分
    [1 2|3 4]
  2. 从未选择的部分中选择一个数放到 当前填充位(swap替换位置即可)
    [1 2 3|4]
  3. 然后继续递归直至填充完毕 将填充好的数组加入集合
    list.add([1,2,3,4])
  4. 回溯,将swap交互的两个数再交换回来,然后选择下一个位置的数与 当前填充位替换

源代码

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>>list=new ArrayList<>();
        backTracking(nums,list,0);
        return list;
    }
    public void swap(int[] arr,int posA,int posB){
        if(posA==posB)return;
        int tmp=arr[posA];
        arr[posA]=arr[posB];
        arr[posB]=tmp;
    }
    public void backTracking(int[] nums,List<List<Integer>> list,int pos){
        if(pos==nums.length){//边界
            ArrayList<Integer>arr=new ArrayList<>();
            for(int i:nums)arr.add(i);
            list.add(arr);
        }
        for(int i=pos;i<nums.length;i++){
            swap(nums,pos,i);
            backTracking(nums,list,pos+1);
            swap(nums,pos,i);
        }
    }
}

力扣top47 全排列2

题目:

给定一个含重复数字的数组 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

nums 中的所有整数 可能相同

分析

使用回溯将所有可能得排列情况记录。

  1. 将当前数组分为左右两部分,左为已经选择并排列的部分,右为还没有选择排列的部分
    [1 2|3 4]

  2. 从未选择的部分中选择一个数放到 当前填充位(swap替换位置即可)

    只能选择未选择过的数字,使用set来保证不选择重复数字,避免额外多余的排列

    [1 2 3|4]

  3. 然后继续递归直至填充完毕 将填充好的数组加入集合
    list.add([1,2,3,4])

  4. 回溯,将swap交互的两个数再交换回来,然后选择下一个位置的数与 当前填充位替换

源代码

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>>list=new ArrayList<>();
        backTracking(nums,list,0);
        return list;
    }
    public void swap(int[] arr,int posA,int posB){
        int tmp=arr[posA];
        arr[posA]=arr[posB];
        arr[posB]=tmp;
    }
    public void backTracking(int[] nums,List<List<Integer>> list,int pos){
        if(pos>=nums.length){
            ArrayList<Integer>arr=new ArrayList<>();
            for(int i:nums)arr.add(i);
            list.add(arr);
            return;
        }
        Set<Integer>set=new HashSet<>();
        backTracking(nums,list,pos+1);
        set.add(nums[pos]);
        for(int i=pos+1;i<nums.length;i++){
            if(set.contains(nums[i]))continue;
            set.add(nums[i]);
            swap(nums,pos,i);
            backTracking(nums,list,pos+1);
            swap(nums,pos,i);
        }
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值