46. Permutations

题目描述(中等难度)

46. Permutations_第1张图片
给定一个 没有重复 数字的序列,返回其所有可能的全排列。

解法一 回溯

其实也算是蛮典型的回溯,利用递归每次向 temp 里添加一个数字,数字添加够以后再回来进行回溯,再向后添加新的解。

可以理解成一层一层的添加,每一层都是一个 for 循环。
46. Permutations_第2张图片
每调用一层就进入一个 for 循环,相当于列出了所有解,然后挑选了我们需要的。其实本质上就是深度优先遍历 DFS

Java

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        List<Integer> tempList = new ArrayList<>();
        backtrace(list,tempList,nums);
        return list;
    }
    private void backtrace(List<List<Integer>> list,List<Integer> tempList,int[] nums){
        if(tempList.size() == nums.length){
            list.add(new ArrayList<>(tempList));
        }else{
            for(int i =0;i<nums.length;i++){
                if(tempList.contains(nums[i])) continue;
                tempList.add(nums[i]);
                backtrace(list,tempList,nums);
                tempList.remove(tempList.size() - 1);
            }
        }
    }
		public static void main(String args[]) {
			int[] nums= {1,2,3};
			List<List<Integer>> ans=permute(nums);
			System.out.println(ans);
		}
}

46. Permutations_第3张图片

Python

class Solution(object):
    def permute(self, nums):
        list1 = []
        tempList = []
        self.backtrace(list1,tempList,nums)
        return list1
    
    def backtrace(self,list1,tempList,nums):
        if(len(tempList) == len(nums)):
            list1.append(list(tempList))
        else:
            for i in range(len(nums)):
                if nums[i] in tempList:
                    continue
                tempList.append(nums[i])
                self.backtrace(list1,tempList,nums)
                del tempList[len(tempList)-1] 

46. Permutations_第4张图片

解法二 交换

假设有一个函数,可以实现题目的要求,即产生 nums 的所有的组合,并且加入到 all 数组中。不过它多了一个参数,begin,即只指定从 nums [ begin ] 开始的数字,前边的数字固定不变。

upset(int[] nums, int begin, List<List<Integer>> all)

如果有这样的函数,那么一切就都简单了。

如果 begin 等于 nums 的长度,那么就表示 begin 前的数字都不变,也就是全部数字不变,我们只需要把它加到 all 中就行了。

if (begin == nums.length) {
    ArrayList<Integer> temp = new ArrayList<Integer>(); 
    for (int i = 0; i < nums.length; i++) {
        temp.add(nums[i]);
    }
    all.add(new ArrayList<Integer>(temp));
    return;
}

如果是其它的情况,我们其实只需要用一个 for 循环,把每一个数字都放到 begin 一次,然后再变化后边的数字就够了,也就是调用 upset 函数,从 begin + 1 开始的所有组合。

for (int i = begin; i < nums.length; i++) {
    swap(nums, i, begin);
    upset(nums, begin + 1, all);
    swap(nums, i, begin);
}

总体就是这样了。

public class permute2 {
	public static List<List<Integer>> permute(int[] nums) {
	    List<List<Integer>> all = new ArrayList<>();
	    //从下标 0 开始的所有组合
	    upset(nums, 0, all);
	    return all;
	}
	private static void upset(int[] nums, int begin, List<List<Integer>> all) {
	    if (begin == nums.length) {
	        ArrayList<Integer> temp = new ArrayList<Integer>(); 
	        for (int i = 0; i < nums.length; i++) {
	            temp.add(nums[i]);
	        }
	        all.add(new ArrayList<Integer>(temp));
	        return;
	    }
	    for (int i = begin; i < nums.length; i++) {
	        swap(nums, i, begin);
	        upset(nums, begin + 1, all);
	        swap(nums, i, begin);
	    }
	}
	private static void swap(int[] nums, int i, int begin) {
	    int temp = nums[i];
	    nums[i] = nums[begin];
	    nums[begin] = temp;
	}
}

你可能感兴趣的:(LeetCode)