Given an array nums
of distinct integers, return all the possible permutations. You can return the answer in any order.
Example 1:
Input: nums = [1,2,3] Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Example 2:
Input: nums = [0,1] Output: [[0,1],[1,0]]
Example 3:
Input: nums = [1] Output: [[1]]
Constraints:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
- All the integers of
nums
are unique.
全排列。
给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
这是backtracking(回溯)类题目的经典题,有模板需要背下来。遇到回溯类型的题,基本思路参见这个帖子,讲的很好。回溯的题一般都需要
- 有一个 helper 函数帮助做 backtracking 的操作
- helper 函数的返回条件是当前子数组的长度满足题意,对于这道题而言,是当前子数组的长度 == 原数组的长度
- 会需要遍历所有可能的选择
- 做过一选择之后要撤销选择,再去做下一个可行的选择,这才叫做回溯嘛对吧
对于这道题,思路是遍历 input 数组,如果没有遍历到某个数字,就加入结果集,然后再回溯。因为这道题的 input 是没有重复数字的,所以其实是不需要去专门检查某一个数字是否有被加入过。而之后的版本二会有出现重复数字,需要额外判断当前数字是否有被遍历过。同时,本题跟 subset 的区别在于,i 指针一定是从 0 开始,因为找的是全排列;而 subset 找的是子集,所以i需要从 start 开始,start 是一直会变化的。
时间O(n! * n)
空间O(n! * n)
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @return {number[][]} 4 */ 5 var permute = function (nums) { 6 let res = []; 7 if (nums === null || nums.length === 0) return res; 8 helper(res, [], nums); 9 return res; 10 }; 11 12 var helper = function (res, list, nums) { 13 if (list.length === nums.length) { 14 res.push(list.slice()); 15 return; 16 } 17 for (let i = 0; i < nums.length; i++) { 18 if (list.includes(nums[i])) { 19 continue; 20 } 21 list.push(nums[i]); 22 helper(res, list, nums); 23 list.pop(); 24 } 25 }
Java实现
1 class Solution { 2 public List<List<Integer>> permute(int[] nums) { 3 List<List<Integer>> res = new ArrayList<>(); 4 helper(res, new ArrayList<>(), nums); 5 return res; 6 } 7 8 private void helper(List<List<Integer>> res, List<Integer> list, int[] nums) { 9 if (list.size() == nums.length) { 10 res.add(new ArrayList<>(list)); 11 return; 12 } 13 for (int i = 0; i < nums.length; i++) { 14 if (list.contains(nums[i])) { 15 continue; 16 } 17 list.add(nums[i]); 18 helper(res, list, nums); 19 list.remove(list.size() - 1); 20 } 21 } 22 }