Leetcode 46 全排列 简单思路以及解法

Leetcode 46 全排列 简单思路以及解法

题目以下:数组

给定一个没有重复数字的序列,返回其全部可能的全排列。code

示例:对象

输入: [1,2,3]递归

输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]rem

思路:it

    拿到题目的时候,看到示例输出,就想着试下回溯解法,采用一个全局的 boolean 数组标识数组中哪些元素被访问过了,递归地产生解集。代码以下:io

class Solution {
    List<List<Integer>> res;// 存放结果的对象
    public List<List<Integer>> permute(int[] nums) {
        res = new ArrayList<List<Integer>>();
        DFS(nums,initializeBooleanArray(nums.length),new ArrayList<Integer>());// 收集全排列的全部排列结果
        return res;
    }
    
    // 循环选择固定哪个数字(选择哪个做为起始数字)
    public void DFS(int[] nums,boolean[] visited,List<Integer> tmp){
        // 若是tmp中存放的数字已经将全部nums中的数字都放入了,那么就将其输入到res中
        if(tmp.size()==nums.length)
            res.add(new ArrayList<Integer>(tmp));
        else{
            // 不然,开始循环遍历,按照0,1,2..的顺序依次选择起点,而后遍历
            for(int i=0;i<nums.length;i++){
                if(visited[i])// 若该点已经被访问过了,则跳过访问下一个点
                    continue;
                else{// 若没被访问过,那么先标记为访问了,而后将其加入tmp中,等待tmp长度足够时写入res中
                    visited[i] = true;
                    tmp.add(nums[i]);
                    DFS(nums,visited,tmp);// 递归调用,经过形参维护的 逻辑栈的变量有:tmp,visited
                    tmp.remove(tmp.size()-1);// 递归结束,还原该点的状态,使得获取下一个组合的遍历还能再通过此点
                    visited[i]=false;// 访问标记还原
                }
            }
        }
    }
    
    // 获取一个与num相等大小的boolean数组
    public boolean[] initializeBooleanArray(int num){
        boolean[] res = new boolean[num];
        for(int i=0;i<num;i++){
            res[i] = false;
        }
        return res;
    }
}

    顺便看了下网上的dalao们的解法,发现有个比较热的解法是交换解法,每次将数与后面的一位进行交换。当交换到最后一位的时候,就将此时的解算入解集中。class

    代码以下:变量

public class Solution {
    
    List<List<Integer>> res;
    
    public List<List<Integer>> permute(int[] nums) {
        res = new LinkedList<List<Integer>>();
        helper(nums, 0);
        return res;
    }
    
    public void helper(int[] nums, int i){
        // 找到转置完成后的解,将其存入列表中
        if(i == nums.length - 1){
            List<Integer> list = new LinkedList<Integer>();
            for(int j = 0; j < nums.length; j++){
                list.add(nums[j]);
            }
            res.add(list);
        }
        // 将当前位置的数跟后面的数交换,并搜索解
        for(int j = i; j < nums.length; j++){
            swap(nums, i , j);
            helper(nums, i + 1);
            swap(nums, i, j);
        }
    }
    
    private void swap(int[] nums, int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}
相关文章
相关标签/搜索