力扣 #46. 全排列(回溯法&&剪枝)

#46. 全排列

給定一個 沒有重複 數字的序列,返回其所有可能的全排列。

示例:

輸入: [1,2,3]
輸出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

思路:

  • 一般輸出所有結果的題目,都是用回溯算法進行深度搜索。
  • 回溯算法一般是如下過程:
def backtrack(路徑, 選擇列表):
    if 滿足結束條件:
        result.add(路徑)
        return
    
    for 選擇 in 選擇列表:
        做選擇
        backtrack(路徑, 選擇列表)
        撤銷選擇

代碼:

LeetCode版

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        int size = nums.length;
        int[] visited = new int[nums.length];
        generate(res,new ArrayList<Integer>(),nums,visited);
        return res;
    }
    public void generate(List<List<Integer>> res, List<Integer> ans, int[] nums, int[] visited){
    	//滿足條件,add路徑。
        //長度是size,添加進結果。
        if(ans.size() == nums.length){
            res.add(new ArrayList<>(ans));
            return;
        } 
        //初始狀態下,ans是空
        //讓每個數字都有開頭的機會
        //nums的所有數字都可以被選擇
        for(int i = 0; i< nums.length;i++){
            if(visited[i] == 1) continue;
			//做選擇
            //取出第i個數字,並標記爲1。
            visited[i] = 1;
            ans.add(nums[i]);
            generate(res,ans,nums,visited);
            //撤銷選擇
            visited[i] = 0;
            ans.remove(ans.size()-1);
        }
    }
}

IDEA版

import java.util.ArrayList;
import java.util.List;

public class number_46 {
    public static void main(String[] args) {
        int[] nums = {1,2,3};
        List<List<Integer>> ll;
        ll = permute(nums);
        System.out.println(ll);
    }

    public static List<List<Integer>> permute(int[] nums){
        //結果數組
        List<List<Integer>> result = new ArrayList<>();
        //標記被訪問過的數字
        int[] visited = new int[nums.length];
        //使用回溯法求解
        back_track(result,new ArrayList<Integer>(),nums,visited);
        return result;
    }

    public static void back_track(List<List<Integer>> result, List<Integer> temp, int[] nums, int[] visited){
        //一次回溯的結果,保存進result,並剪枝。
        if(temp.size() == nums.length){
            result.add(new ArrayList<>(temp));
            return;
        }
        //循環選擇第一個進temp的元素
        for (int i = 0; i < nums.length; i++) {
            //跳過訪問過的元素,剪枝。
            if(visited[i] == 1) continue;
            //標記被訪問過的元素
            visited[i] = 1;
            temp.add(nums[i]);
            //遞歸
            back_track(result,temp,nums,visited);
            //恢復現場,並將尾部彈出。
            visited[i] = 0;
            temp.remove(temp.size()-1);
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章