1. 程式人生 > 其它 >46.全排列

46.全排列

46.全排列

題目

給定一個不含重複數字的陣列 nums ,返回其 所有可能的全排列 。你可以 按任意順序 返回答案。

示例 1:
輸入:nums = [1,2,3]
輸出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:
輸入:nums = [0,1]
輸出:[[0,1],[1,0]]

示例 3:
輸入:nums = [1]
輸出:[[1]]

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/permutations
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

題解

分析之後發現這道題還是在列舉所有的可能性,那麼準備採用回溯法。

抽象樹中,可以看出排列中[1,2]和[2,1]是兩種不同的選擇,而在組合中是一樣。那就不需要使用startIndex來控制。組合問題其實取數有一規律都是從前往後選,但是排序不一樣的,那麼在取值的時候就需要判斷之前的數是否被選了。

遞迴的引數和返回值

nums:輸入的陣列
path:存放單次排序的路徑

List<List<Integer>> res = new ArrayList<>();
void backtracing(int[] nums,List<Integer> path);

遞迴的終止條件

遞迴的層數是確定的,只要所有的數都排列了就結束了

if(path.size() == nums.length){
	res.add(path);
	return;
}

遞迴的單層邏輯

每一次取值都需要從頭到尾選擇,不能取已經取過的值,那怎麼表示值已經取過了?path的路徑之中有就說明已經取值了,沒有就說明還沒有取過值

還可以設定一個visited陣列記錄元素是否被訪問過。

for(int i =0;i<nums.length;i++){
   if(path.cantains(i))continue; //表示已經取過了,那就不能去跳到下一個
   path.add(i);
   backtracing(nums,path);
   path.remove(path.size()-1);
}

程式碼

class Solution {
    List<List<Integer>> res ;
    public List<List<Integer>> permute(int[] nums) {
        res = new ArrayList<>();
        backtracing(nums,new ArrayList<>());
        return res;
    }
    void backtracing(int[] nums,List<Integer> path){
        if(path.size() == nums.length){
	        res.add(new ArrayList(path));
        	return;
        }
        for(int num:nums){
            if(path.contains(num))continue;
            path.add(num);
            backtracing(nums,path);
            path.remove(path.size()-1);
        }
    }
}