回溯法求解Leetcode经典排列问题(Leetcode 46、47、996)

写在前面:

求解排列问题常用的方法是回溯,回溯类似于DFS(深度优先遍历),实际是一个暴力搜索的过程,把所有的排列都列举出来,找出符合题意的排列。组合问题与元素顺序无关,而排列问题与元素的顺序有关。

1、46. Permutations

题意:

给出一个不含重复元素的数组,求所有可能的排列。

代码:

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        backtrack(res,new ArrayList<>(),nums);
        return res;
    }
    public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums){
        if(list.size()==nums.length){
            res.add(new ArrayList<>(list));
        }
        for(int i=0;i<nums.length;i++){
            if(list.contains(nums[i])){
                continue;
            }
            list.add(nums[i]);
            backtrack(res,list,nums);
            list.remove(list.size()-1);
        }
    }
}

2、47. Permutations II

题意:

给出一个可能含重复元素的数组,求所有可能的排列。

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        Arrays.sort(nums);
        boolean[] visited=new boolean[nums.length];
        backtrack(res,new ArrayList<>(),nums,visited);
        return res;
    }
    public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums,boolean[] visited){
        if(list.size()==nums.length){
            res.add(new ArrayList<>(list));
        }
        for(int i=0;i<nums.length;i++){
            if(visited[i]){
                continue;
            }
            if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]){
                continue;
                //这一步的剪枝参考https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-3/
            }
            visited[i]=true;
            list.add(nums[i]);
            backtrack(res,list,nums,visited);
            list.remove(list.size()-1);
            visited[i]=false;
        }
    }
}

3、996. Number of Squareful Arrays

题意

给出一个可能含重复元素的数组,求满足相邻元素之和为平方数的排列的数量。

class Solution {
    public int numSquarefulPerms(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        Arrays.sort(nums);
        boolean[] visited=new boolean[nums.length];
        backtrack(res,new ArrayList<>(),nums,visited);
        return res.size();
    }
     public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums,boolean[] visited){
        if(list.size()==nums.length){
            res.add(new ArrayList<>(list));
        }
        for(int i=0;i<nums.length;i++){
            if(visited[i]){
                continue;
            }
            if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]){
                continue;
            }
            if(!list.isEmpty()&&isPerfectSquare(nums[i]+list.get(list.size()-1)) || list.isEmpty()){
                visited[i]=true;
                list.add(nums[i]);
                backtrack(res,list,nums,visited);
                list.remove(list.size()-1);
                visited[i]=false;
            }
        }
    }
    public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums){
        if(list.size()==nums.length){
            res.add(new ArrayList<>(list));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(list.contains(nums[i])){
                continue;
            }
            if(!list.isEmpty()&&isPerfectSquare(nums[i]+list.get(list.size()-1)) || list.isEmpty()){
                list.add(nums[i]);
                backtrack(res,list,nums);
                list.remove(list.size()-1);
            }
        }
    }
    public boolean isPerfectSquare(int n){
        if((int)Math.sqrt(n)*(int)Math.sqrt(n)==n){
            return true;
        }
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值