【DFS】Permutations

34 篇文章 0 订阅
29 篇文章 0 订阅

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].

解法一:DFS,递归时当前元素和其后的元素进行交换排列

public class Solution {
    
    private ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    
    public void dfs(int[] num, int pos){
        if(pos == num.length){
            ArrayList<Integer> l = new ArrayList<Integer>();
            for(int i=0; i<num.length; i++)
            l.add(num[i]);
            res.add(l);
            return;
        }
        
        for(int i=pos; i<num.length; i++){//exchange
            int temp = num[pos];
            num[pos] = num[i];
            num[i] = temp;
            
            dfs(num, pos+1);//pos遍历层次
            num[i] = num[pos];
            num[pos] = temp;
        }
    }
    
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        Arrays.sort(num);
        dfs(num, 0);
        
        return res;
    }
}
解法二:参考 http://blog.csdn.net/u011095253/article/details/9158403

这次,我们要生成完整的序列了,那么和上次的Subset有什么不同呢?

1. 添加进res的时间,上面题我们每添加一个数字到tmp里,就可以往res里面添加,而这次,我们要生成完整的序列,所以需要当tmp.size()==序列长度的时候再往res里面添加

2. 每次不能从pos开始往数组尾巴扫了,因为我们要求的不是Subset而是完整序列,所以要从第一个数字开始往数组尾巴扫,问题又来了,我们怎么知道取没取过这个元素呢,那么我们就创建一个boolean[] visit 每此添加的时候给相对应位置置True,删去的时候置False


public class Solution {
    
    private ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    
    public void dfs(ArrayList<Integer> l, int[] num, int[] flag){
        if(l.size() == num.length){
            res.add(new ArrayList(l));
            return;
        }
        
        for(int i=0; i<num.length; i++){
            if(flag[i] == 1) continue;
            
            l.add(num[i]);
            flag[i] = 1;
            dfs(l, num, flag);//不是new ArrayList(l)
            l.remove(l.size() -1);
            flag[i] = 0;
        }
    }
    
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        ArrayList<Integer> l = new ArrayList<Integer>();
        int [] flag = new int[num.length];
        Arrays.sort(num);
        dfs(l,num,flag);
        
        return res;
    }
}
解法三:使用字典序法
public class Solution {
    
    private ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        int [] flag = new int[num.length];
        Arrays.sort(num);
        
        int i = num.length-1;
        int pos, j;
        while(i>=0){
            
            ArrayList<Integer> l = new ArrayList<Integer>();
            for(int k=0; k<num.length; k++){
                l.add(num[k]);
            }
            res.add(l);
            
            pos = i-1;
            while(pos>=0 && pos<num.length-1 && num[pos] >= num[pos+1]) pos--;//从后往前求num[i]<num[i+1]的节点i
            
            if(pos >= 0){//若已经按大到小的顺序排列则推出循环,否则,从后往前求比i节点大的节点
                j = num.length - 1;
                while(j>=0 && num[j] <= num[pos]) j--;//节点j,num[j]>num[i]
                
                if(j>=0)
                swap(num, pos, j);//交换i,j
                
                if(pos < num.length-1)
                reverse(num, pos+1);//将i后的所有节点反转
                
                i = num.length-1;//重新从最后一个节点求
            }
            else{
                break;
            }
        }
        
        return res;
    }
    
    public void reverse(int [] num, int pos){
        for(int i=num.length-1; i>=pos;){
            int temp = num[i];
            num[i] = num[pos];
            num[pos] = temp;
            i--;
            pos++;
        }
    }
    
    public void swap(int[] num, int i, int j){
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
        
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值