LeetCode 46. 全排列 --javascript DFS

46. 全排列

描述

給定一個不含重複數字的數組 nums ,返回其 全部可能的全排列 。你能夠 按任意順序 返回答案。javascript

示例 1:java

輸入: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]]
複製代碼

提示:markdown

1 <= nums.length <= 6
-10 <= nums[i] <= 10
複製代碼

題解

回溯法

回溯法(backtracking)是優先搜索的一種特殊狀況,又稱爲試探法,經常使用於須要記錄節點狀態的深度優先搜索。一般來講,排列、組合、選擇類問題使用回溯法比較方便。 顧名思義,回溯法的核心是回溯。在搜索到某一節點的時候,若是咱們發現目前的節點(及其子節點)並非需求目標時,咱們回退到原來的節點繼續搜索,而且把在目前節點修改的狀態 還原。spa

這樣的好處是咱們能夠始終只對圖的總狀態進行修改,而非每次遍歷時新建一個圖來儲存 狀態。 在具體的寫法上,它與普通的深度優先搜索同樣,都有 [修改當前節點狀態]→[遞歸子節 點] 的步驟,只是多了回溯的步驟,變成了 [修改當前節點狀態]→[遞歸子節點]→[回改當前節點 狀態]。 回溯法。有兩個小訣竅,一是按引用傳狀態,二是全部的狀態修 改在遞歸完成後回改。 回溯法修改通常有兩種狀況,一種是修改最後一位輸出,好比排列組合;一種是修改訪問標 記,好比矩陣裏搜字符串。code

分析

怎樣輸出全部的排列方式呢?對於每個當前位置 i,咱們能夠將其於以後的任意位置交換, 而後繼續處理位置 i+1,直處處理到最後一位。爲了防止咱們每此遍歷時都要新建一個子數組儲 存位置 i 以前已經交換好的數字,咱們能夠利用回溯法,只對原數組進行修改,在遞歸完成後再 修改回來。 咱們以樣例[1,2,3]爲例,按照這種方法,咱們輸出的數組順序爲[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]],能夠看到全部的排列在這個算法中都被考慮到了。orm

coding

/** * @param {number[]} nums * @return {number[][]} */
var permute = function(nums) {
   let ans = [];
   let start = 0, len = nums.length, _start = 0;
   backtracking(nums, start, ans);
   return ans;
};

const backtracking = function(_nums, level, ans) {
    if(level === _nums.length - 1) {
        ans.push([..._nums]);
        return;
    }
    for(let i = level; i < _nums.length; i++) {
        [_nums[i], _nums[level]] = [_nums[level], _nums[i]] // 修改當前節點狀態
        backtracking(_nums, level + 1, ans); // 遞歸子節點
        [_nums[i], _nums[level]] = [_nums[level], _nums[i]] // 恢復當前節點狀態
    }
}

複製代碼
相關文章
相關標籤/搜索