leetcode47. 全排列 II(回溯算法-java)

文章介绍了LeetCode第47题全排列II的解题方法,重点在于使用回溯算法并添加剪枝策略处理重复数字的情况。给定一个可能含有重复数字的序列nums,目标是返回所有不重复的全排列。文章提供了详细的解题思路和Java代码实现,并给出了示例输入和输出。此外,还提到了其他相关的回溯算法题目。

leetcode47. 全排列 II

来源:力扣(LeetCode)
链接:https://leetcode.cn/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

解题思路

排列问题本身就是让你穷举元素的位置
但这个问题里,会有重复数字,因此我们要进行剪枝.
比如输入 nums = [2,2’,2’‘],产生的回溯树如下:,2’,2’’ 只是为了区分三个2.
他的全排列就是下图:
在这里插入图片描述
上面虽然有六个结果,但其实五个是重复的,实际只有一种情况.
我们要在排列时,对相同的情况进行剪枝.
如下图:
在这里插入图片描述
我们要把红色部分全部剪掉,因此就要有个标记,在没有重复的情况下,进行剪枝.
本题也是回溯算法的框架来做,只是要做好剪枝的问题.
再看一眼回溯算法的框架:
result = []
void process(选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择

代码演示

class Solution {
	//记录答案
    List<List<Integer>> ans = new ArrayList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        process(nums,0);
        return ans;
    }
	/**
	* 回溯算法
	*/
    public void process(int[]nums,int index){
        if(index == nums.length){
            ans.add(toList(nums));
            return ;
        }
        //用来标记相同的元素,
        HashMap<Integer,Boolean> flag = new HashMap<>();
        for(int i = index;i < nums.length;i++){
        //前面没有做出过选择,才进行选择
            if(!flag.containsKey(nums[i])){
            //已经做了选择,就加到标记里
                flag.put(nums[i],true);
                //全排列是对元素出现位置的穷举,因此我们把他交换到别的位置上,继续进行递归,
        		//来让他去出现在不同的位置上
        		//这一步就是做选择,
                swap(nums,i,index);
                process(nums,index + 1);
                //撤销选择
                swap(nums,i,index);
            }
        }
    }
    
	/**
	* 交换的方法
	*/
    public void swap(int[]nums,int i,int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
	/**
	* 数组转集合
	*/
    public List<Integer> toList(int[]nums){
        List<Integer> ans = new ArrayList<>();
        for(int a : nums){
            ans.add(a);
        }
        return ans;
    }
}

回溯算法专题

leetcode46. 全排列

leetcode39. 组合总和

leetcode216. 组合总和 III

leetcode90. 子集 II

leetcode40. 组合总和 II

leetcode77. 组合

leetcode78 子集

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值