leecode/problems/46.permutations.md
2020-05-22 18:17:19 +08:00

178 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 题目地址
https://leetcode.com/problems/permutations/description/
## 题目描述
```
Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
```
## 思路
这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。
这种题目其实有一个通用的解法,就是回溯法。
网上也有大神给出了这种回溯法解题的
[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。
除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。
我们先来看下通用解法的解题思路,我画了一张图:
![backtrack](../assets/problems/backtrack.png)
通用写法的具体代码见下方代码区。
## 关键点解析
- 回溯法
- backtrack 解题公式
## 代码
* 语言支持: Javascript, Python3
Javascript Code:
```js
/*
* @lc app=leetcode id=46 lang=javascript
*
* [46] Permutations
*
* https://leetcode.com/problems/permutations/description/
*
* algorithms
* Medium (53.60%)
* Total Accepted: 344.6K
* Total Submissions: 642.9K
* Testcase Example: '[1,2,3]'
*
* Given a collection of distinct integers, return all possible permutations.
*
* Example:
*
*
* Input: [1,2,3]
* Output:
* [
* [1,2,3],
* [1,3,2],
* [2,1,3],
* [2,3,1],
* [3,1,2],
* [3,2,1]
* ]
*
*
*/
function backtrack(list, tempList, nums) {
if (tempList.length === nums.length) return list.push([...tempList]);
for(let i = 0; i < nums.length; i++) {
if (tempList.includes(nums[i])) continue;
tempList.push(nums[i]);
backtrack(list, tempList, nums);
tempList.pop();
}
}
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
const list = [];
backtrack(list, [], nums)
return list
};
```
Python3 Code:
```Python
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
"""itertools库内置了这个函数"""
return itertools.permutations(nums)
def permute2(self, nums: List[int]) -> List[List[int]]:
"""自己写回溯法"""
res = []
def _backtrace(nums, pre_list):
if len(nums) <= 0:
res.append(pre_list)
else:
for i in nums:
# 注意copy一份新的调用否则无法正常循环
p_list = pre_list.copy()
p_list.append(i)
left_nums = nums.copy()
left_nums.remove(i)
_backtrace(left_nums, p_list)
_backtrace(nums, [])
return res
```
Python Code:
```Python
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
"""itertools库内置了这个函数"""
import itertools
return itertools.permutations(nums)
def permute2(self, nums: List[int]) -> List[List[int]]:
"""自己写回溯法"""
res = []
def _backtrace(nums, pre_list):
if len(nums) <= 0:
res.append(pre_list)
else:
for i in nums:
# 注意copy一份新的调用否则无法正常循环
p_list = pre_list.copy()
p_list.append(i)
left_nums = nums.copy()
left_nums.remove(i)
_backtrace(left_nums, p_list)
_backtrace(nums, [])
return res
def permute3(self, nums: List[int]) -> List[List[int]]:
"""回溯的另一种写法"""
res = []
length = len(nums)
def _backtrack(start=0):
if start == length:
# nums[:] 返回 nums 的一个副本,指向新的引用,这样后续的操作不会影响已经已知解
res.append(nums[:])
for i in range(start, length):
nums[start], nums[i] = nums[i], nums[start]
_backtrack(start+1)
nums[start], nums[i] = nums[i], nums[start]
_backtrack()
return res
```
## 相关题目
- [31.next-permutation](./31.next-permutation.md)
- [39.combination-sum](./39.combination-sum.md)
- [40.combination-sum-ii](./40.combination-sum-ii.md)
- [47.permutations-ii](./47.permutations-ii.md)
- [60.permutation-sequence](./60.permutation-sequence.md)
- [78.subsets](./78.subsets.md)
- [90.subsets-ii](./90.subsets-ii.md)
- [113.path-sum-ii](./113.path-sum-ii.md)
- [131.palindrome-partitioning](./131.palindrome-partitioning.md)