三道回溯算法的全排列题(重复+非重复)

在这里插入图片描述

这一题是没有重复数字的排列,采用回溯算法,可以采用交换的方式实现回溯,也可以暴力回溯然后剪枝

交换实现回溯

class Solution {
    
    
    List<List<Integer>> res=new LinkedList<>();
     
    int arr[];
    public List<List<Integer>> permute(int[] nums) {
    
    
        arr=nums;
        backtrack(0);
        return res;

    }
    public void backtrack(int x)
    {
    
    
         if(x==arr.length-1)
         {
    
       List<Integer> list=new ArrayList<>();
             for(int i=0;i<arr.length;i++)
             {
    
    
                 list.add(arr[i]);
             }
             res.add(list);
             return;
         }
         
        for(int i=x;i<arr.length;i++)
        {
    
    
           
            swap(i,x);
            backtrack(x+1);
            swap(x,i);
          
        }
            
    }
     public void swap(int i,int x)
    {
    
    
        int temp=arr[i];
        arr[i]=arr[x];
        arr[x]=temp;
    }
}

使用剪枝实现全排列

class Solution {
    
    
    List<List<Integer>> res=new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
    
    
        LinkedList<Integer> list=new LinkedList<>();
        backtrack(nums,list);
        return res;

    }
    public void backtrack(int nums[],LinkedList<Integer> list)
    {
    
    
         if(list.size()==nums.length)
         {
    
    
             res.add(new LinkedList(list));
             return;
         }
        for(int i=0;i<nums.length;i++)
        {
    
    
            if(list.contains(nums[i]))
                continue;
            list.add(nums[i]);
            backtrack(nums,list);
            list.removeLast();
        }
            
    }
}

在这里插入图片描述

这一题是有重复的排列,采用交换实现回溯时要进行判断是否有重复元素

class Solution {
    
    
    List<List<Integer>> res=new LinkedList<>();     
    int arr[];
    public List<List<Integer>> permuteUnique(int[] nums) {
    
    
         arr=nums;
        backtrack(0);
        return res;

    }
    public void backtrack(int x)
    {
    
    
     if(x==arr.length-1)
         {
    
       List<Integer> list=new ArrayList<>();
             for(int i=0;i<arr.length;i++)
             {
    
    
                 list.add(arr[i]);
             }
             res.add(list);
             return;
         }
      
         List<Integer> list1=new ArrayList<>();
        for(int i=x;i<arr.length;i++)
        {
    
    
             if(list1.contains(arr[i]))
                 continue;
            list1.add(arr[i]);
            swap(i,x);
            backtrack(x+1);
            swap(x,i);
          
        }
            
    }
     public void swap(int i,int x)
    {
    
    
        int temp=arr[i];
        arr[i]=arr[x];
        arr[x]=temp;
    }
}

在这里插入图片描述

这一题也是有重复的排列,采用交换的方法同上一题

class Solution {
    
    
    LinkedList<String> lists=new LinkedList<>();
    char c[];
       
    public String[] permutation(String s) {
    
    
        c=s.toCharArray();
        backTrack(0);
        return lists.toArray(new String[lists.size()]);

    }
    public void backTrack(int x)
    {
    
         
          if(x==c.length-1)//满足条件,得到一个排列
          {
    
    
              lists.add(String.valueOf(c));
              return;
          }
        List<Character> list=new ArrayList<>();
        for(int i=x;i<c.length;i++)
        {
    
    
            if(list.contains(c[i]))
                continue;
            list.add(c[i]);//防止出现 aab这种重复情况 a只做为第一位出现1次
            swap(i,x);//交换,将c[i]固定在位置x上
            backTrack(x+1);
            swap(x,i);//恢复交换
        }
    }
    public void swap(int i,int x)
    {
    
    
        char temp=c[i];
        c[i]=c[x];
        c[x]=temp;
    }
}

总结:对于全排列的情况可以采用交换的方法实现回溯,比较简单,没有重复时直接交换,也不用剪枝,因为每次dfs(i+1),保证了不会重复,如果是重复的情况,需要用一个list集合保存加入的元素来判断后面是否还会出现

猜你喜欢

转载自blog.csdn.net/qq_43478694/article/details/115439233