1. 程式人生 > >【演算法】求全排列 回溯 交換 DFS JAVA

【演算法】求全排列 回溯 交換 DFS JAVA

思路簡述:

一個全排列其實就是一條把陣列無重複遍歷一遍的DFS過程

思路一:簡單回溯,

1. 一個List存遍歷路徑,從第N個“結點”到第N+1個“結點”是隻需要找一個未遍歷的結點就行

2. 一個關鍵點在於查詢 下一個可遍歷“結點”, 可以用SET輔助List存放已遍歷結點,List中存遍歷書序(文中方法未用SET,複雜度較高,但是可以在Leetcode上AC);也可用一個數據結構完成:LinkedHashMap,即可儲存插入順序,也可O(1)判斷是否存在某元素。

3. 回溯: 選中某一子“結點”遞迴下去之後,要回溯查詢另一“子節點”,這就是回溯的過程,通過把某時刻路徑中最後結點刪除,新增下一“子節點”實現

程式碼

public List<List<Integer>> permute(int[] num) {
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        if(num == null || num.length < 1) return res;
        bt(res, new ArrayList<Integer>(), 0, num);
        return res;
    }
    
    public void bt(List<List<Integer>> res, final List<Integer> cur, int now, int[] num){
        int length = num.length;
        if(cur.size() >= length) {
            res.add(new ArrayList<Integer>(){
                {
                    addAll(cur);
                }
            });
            return ;
        }
        for(int i = now; i < length || i % length < now; i++){//回溯
        	if(cur.contains(num[i % length])) continue;//判斷回溯的元素是否已加入當前組合中
            cur.add(num[i % length]);
            bt(res, cur, (i  + 1)% length, num);
            cur.remove(cur.size() - 1);
        }
    }

思路二:

 基於思路一,不需要輔助List存放遍歷路徑,原陣列就是遍歷路徑

每次尋找下一遍歷結點的過程可以轉化為,將後一結點交換到當前結點的過程

還原交換的過程就是回溯的過程

public List<List<Integer>> permute(int[] num) {
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        if(num == null || num.length < 1) return res;
        bt(res, new ArrayList<Integer>(), 0, num);
        return res;
    }
    
    public void bt(List<List<Integer>> res, final List<Integer> cur, int now, final int[] num){
        int length = num.length;
        if(now >= length) {
            res.add(new ArrayList<Integer>(){
                {
                	for(int i: num)
                    add(i);
                }
            });
            return ;
        }
//        for(int i = now; i < length || i % length < now; i++){
//        	if(cur.contains(num[i % length])) continue;
//            cur.add(num[i % length]);
//            bt(res, cur, (i  + 1)% length, num);
//            cur.remove(cur.size() - 1);
//        }
        for(int i = now; i < length; i++){
        	swap(num, now, i);
        	bt(res, cur, now + 1, num);
        	swap(num, now, i);
        }
        
    }
    
    public void swap(int[] nums, int idx1, int idx2){
    	int temp = nums[idx1];
    	nums[idx1] = nums[idx2];
    	nums[idx2] = temp;
    }