LeetCode——47. 全排列 II(这次要彻底搞懂全排列)

题目描述:

在这里插入图片描述

解题思路:

之前博客总结过全排列的写法,就是一个递归,交换元素就行了,但是总结的方法是不含有重复元素的全排列,这道题,给的元素是重复的,所以需要稍微的修改一下。
含有重复元素的全排列,主要就是在理解了一般的全排列后,思考去除或者叫剪枝,方法很多。
有两种方法,先说第一种吧,声明一个list,在进行排列的时候将第一个交换的元素放入,然后之后判断的时候,如果已经包含了这个元素,就不进行全排列,这个思路是看这里理解的。
直接给出代码吧。

  public List<List<Integer>> permuteUnique(int[] nums) {

        List<List<Integer>> lists=new ArrayList<>();
        qpl(0,nums,lists);
        return lists;
    }

    void qpl(int begin,int[] nums,List<List<Integer>> lists)
    {
        List<Integer> exit=new ArrayList<>();
        if(begin==nums.length)
        {
            List<Integer> list=new ArrayList<>();
            for (int i = 0; i < nums.length; i++) {
                list.add(nums[i]);
            }
            lists.add(list);
            return;
        }

        for (int i = begin; i <nums.length ; i++) {
            if(!exit.contains(nums[i]))
            {
                exit.add(nums[i]);
            swap(nums,i,begin);
            qpl(begin+1,nums,lists);
            swap(nums,i,begin);
            }


        }
    }

    private void swap(int[] nums, int i, int begin) {
        int temp=nums[i];
        nums[i]=nums[begin];
        nums[begin]=temp;
    }

另一种方法是蓝桥杯视频里面讲解的一种方法,抓取理解,但是要先事先排好序,感觉没有第一种方法好理解,也没第一种方法方便,下面也给出代码。

class Solution {
      public static List<List<Integer>> permuteUnique(int[] nums) {
          Arrays.sort(nums);//首先排序,有序的才可以
        List<List<Integer>> lists=new ArrayList<>();
        boolean[] vis=new boolean[nums.length];
        int[] path=new int[nums.length];
        dfs(nums,0,path,vis,lists);
        return lists;
    }

    static void dfs(int[] nums,int n,int[] path,boolean[] vis,List<List<Integer>> lists){

        if(n==nums.length)
        {
            List<Integer> list=new ArrayList<>();
            for (int i = 0; i < nums.length; i++) {
                list.add(path[i]);
            }
            lists.add(list);
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            //和上一个元素相同,而且上一个元素没有被访问过
            if(i>0&&nums[i]==nums[i-1]&&!vis[i-1])
            {
                continue;//不抓取
            }
            if(!vis[i])
            {
                vis[i]=true;
                path[n]=nums[i];
                dfs(nums,n+1,path,vis,lists);
                vis[i]=false;
            }
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值