题目:
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
Example:
Input: [1,1,2]
Output:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
这次有重复需要去重,46题的解法1和解法2无需修改仍可使用
解法1:
调用函数next_permutation
首先输入的序列不一定是排序好的,首先要先排序,注意使用do while 结构,第一个排列也要加进去
c++:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());
do{
res.push_back(nums);
} while(next_permutation(nums.begin(),nums.end()));
return res;
}
};
解法2:
用LeetCode 刷题记录31. 31. Next Permutation的函数
函数需要点改进,原函数没有返回数据,现在我们需要返回true或者false,表示是否结束
- 如果排列为1位,自然没有下一个排列,返回false
- 如果最后需要整个反转即说明到达了最后一个排列,如3 2 1 ,不需要再进行了,返回false
c++:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());
do{
res.push_back(nums);
} while(nextPermutation(nums));
return res;
}
bool nextPermutation(vector<int>& nums) {
int n = nums.size();
if(n <= 1) return false;
int i = n - 2;
int j = n - 1;
while(i >= 0 && nums[i] >= nums[i + 1]) --i;
if(i >= 0){
while(j >= 0 && nums[j] <= nums[i]) --j;
swap(nums[i] , nums[j]);
}
if(i == -1){
//reverse(nums.begin(), nums.end());
return false;
} else {
reverse(nums.begin() + i + 1 , nums.end());
return true;
}
}
};
java:
java需要将int[] 数组转成List list,详见Java:ArrayList和数组int[]的相互转化
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
List<Integer> list = null;
do{
list = Arrays.stream(nums).boxed().collect(Collectors.toList());
res.add(list);
} while(nextPermutation(nums));
return res;
}
public boolean nextPermutation(int[] nums) {
int n = nums.length;
if(nums == null || n <= 1) return false;
int i = n - 2;
int j = n - 1;
while(i >= 0 && nums[i] >= nums[i + 1]) --i;
if(i >= 0){
while(j >= 0 && nums[j] <= nums[i]) --j;
swap(nums, i, j);
}
if(i == -1){
//reverse(nums, 0 , n - 1);
return false;
} else {
reverse(nums, i + 1 , n - 1);
return true;
}
}
private void reverse(int[] nums, int start, int end){
int i = start;
int j = end;
while(i < j){
swap(nums, i, j);
i++;
j--;
}
}
private void swap(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
python:
- python中没有do while 函数
- append函数添加nums时,添加的是引用,所以后面添加的会改变前面的元素,所以要用深拷贝append操作被覆盖 ,此外可以用res.append(nums[:])来创建新的对象
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
nums.sort()
temp = copy.deepcopy(nums)
res.append(temp)
while self.nextPermutation(nums):
temp = copy.deepcopy(nums)
res.append(temp)
return res
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
if nums == None or n <= 1: return False
i = n - 2
j = n - 1
while i >= 0 and nums[i] >= nums[i + 1]: i -= 1
if i >= 0:
while j >= 0 and nums[j] <= nums[i]: j -= 1
nums[i] , nums[j] = nums[j], nums[i]
if i == -1:
return False
else:
start = i + 1
end = n - 1
while start < end:
nums[start] , nums[end] = nums[end], nums[start]
start, end = start + 1, end - 1
return True
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
nums.sort()
temp = copy.deepcopy(nums)
res.append(temp)
print res
while self.nextPermutation(nums):
# temp = copy.deepcopy(nums)
# res.append(temp)
res.append(nums[:])
return res
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
if nums == None or n <= 1: return False
i = n - 2
j = n - 1
while i >= 0 and nums[i] >= nums[i + 1]: i -= 1
if i >= 0:
while j >= 0 and nums[j] <= nums[i]: j -= 1
nums[i] , nums[j] = nums[j], nums[i]
if i == -1:
start = i + 1
end = n - 1
while start < end:
nums[start] , nums[end] = nums[end], nums[start]
start, end = start + 1, end - 1
print nums
return False
else:
start = i + 1
end = n - 1
while start < end:
nums[start] , nums[end] = nums[end], nums[start]
start, end = start + 1, end - 1
return True
解法3:
与46题的不同,首先需要排序,然后需要
if(i > 0 && nums[i] == nums[i-1] && visited[i-1] == 0) continue;
来去重,解释见[LeetCode] 47. Permutations II 全排列之二
注意:
- 不能不加visited[i-1] == 0,如果不加这个条件 如 1 2a 2b,当结果已经有1 2a,再加入2b时便不能加入了,显然是错的
- 条件visited[i-1] == 0或者visited[i-1] == 1都可以
前者 结果有1 2a ,再加入2b,此时visited[1] == 1可以加入
但是当2a出栈,回退时此时visited[1] == 0,结果1 ,不能加入2b
后者 结果有1 2a ,此时visited[1] == 1,不可以加入2b
但是当2a出栈,回退时此时visited[1] == 0,结果1 ,能加入2b,进而继续加入2a
显然前者效率更高
c++:
class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> res;
int n = nums.size();
vector<int> path,visited(n, 0);
sort(nums.begin(),nums.end());
DFS(nums, path, visited,res,0);
return res;
}
void DFS(vector<int>& nums,vector<int>& path,vector<int>& visited,vector<vector<int>>& res,int index) {
if(index == nums.size()){
res.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i++){
if(visited[i] == 1) continue;
if(i > 0 && nums[i] == nums[i-1] && visited[i-1] == 0) continue;
//if(i > 0 && nums[i] == nums[i-1] ) continue;
//cout << nums[i] << " " << i << " "<<index<<endl;
path.push_back(nums[i]);
visited[i] = 1;
DFS(nums, path, visited,res,index + 1);
path.pop_back();
visited[i] = 0;
}
}
};
java:
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] visited = new boolean[nums.length];
Arrays.sort(nums);
DFS(nums, path, res, visited, 0);
return res;
}
private void DFS(int[] nums,List<Integer> path,List<List<Integer>> res,boolean[] visited,int index){
if(index == nums.length){
res.add(new ArrayList<>(path));
return;
}
for(int i = 0; i < nums.length; ++i){
if(visited[i] == true) continue;
if(i > 0 && nums[i] == nums[i-1] && visited[i-1] == false) continue;
path.add(nums[i]);
visited[i] = true;
DFS(nums, path, res,visited , index + 1);
path.remove(path.size() - 1);
visited[i] = false;
}
}
}
python:
class Solution(object):
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
path = []
visited = [0] * len(nums)
nums.sort()
self.DFS(nums, path, res, visited, 0)
return res
def DFS(self, nums, path, res,visited,index):
if index == len(nums):
res.append(path)
return
for i in xrange(len(nums)):
if visited[i] == 1: continue
if i > 0 and nums[i] == nums[i-1] and visited[i-1] == 0: continue
visited[i] = 1
self.DFS(nums, path + [nums[i]], res, visited, index + 1)
#self.DFS(nums, path, res, visited, index + 1)
visited[i] = 0
解法4:
递归法(交换)
用一个set记录已经交换过的,如有重复则不进行交换
如第一行:1和1自己交换,记录1,1和2a交换,记录2a,将要1和2b交换,发现set中已经有2a,则不进行交换,避免了重复
可以提前进行排序,也可以不用,提前排序效率高一点
c++
class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());
DFS(nums, res,0);
return res;
}
void DFS(vector<int>& nums,vector<vector<int>>& res,int start) {
if(start == nums.size()){
res.push_back(nums);
return;
}
set<int> s;
for(int i = start; i < nums.size(); i++){
if(s.count(nums[i]) != 0) continue;
s.insert(nums[i]);
swap(nums[start], nums[i]);
DFS(nums,res,start + 1);
swap(nums[start], nums[i]);
}
}
};
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
DFS(nums, res, 0);
return res;
}
private void DFS(int[] nums,List<List<Integer>> res,int start){
if(start == nums.length){
List<Integer> temp = new ArrayList<Integer>();
for (int i = 0; i < nums.length; i++) {
temp.add(nums[i]);
}
res.add(new ArrayList<>(temp));
return;
}
Set<Integer> st = new HashSet<>();
for(int i = start; i < nums.length; ++i){
if(st.contains(nums[i])) continue;
st.add(nums[i]);
swap(nums,start,i);
DFS(nums, res, start + 1);
swap(nums,start,i);
}
}
private void swap(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
python:
class Solution(object):
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
res = []
self.DFS(nums, res, 0)
return res
def DFS(self, nums, res,start):
if start == len(nums):
res.append(nums[:])
return
s = set()
for i in xrange(start,len(nums)):
if nums[i] in s: continue
s.add(nums[i])
nums[start], nums[i] = nums[i],nums[start]
self.DFS(nums, res, start + 1)
nums[start], nums[i] = nums[i],nums[start]