给出一个具有重复数字的列表,找出列表所有不同的排列
您在真实的面试中是否遇到过这个题?
Yes
样例
给出列表[1,2,2],不同的排列有:
[
[1,2,2],
[2,1,2],
[2,2,1]
]
挑战
能否不使用递归完成?
标签 Expand
相关题目 Expand
解题思路:
/*
* 将所有的排列保存在list中 利用交换的思想,
* 先,求所有可能出现在第一个位置的字符,
*
* 其次,把第一个字符和其后面的字符一一交换。如下图所示,分别把第一个字符a和后面的b、c等字符交换的情形。
*
* 接着,固定第一个字符,求后面所有字符的排列。这个时候我们仍把后面的所有字符分成两部分:后面字符的第一个字符,以及这个字符之后的所有字符。
* 然后把第一个字符逐一和它后面的字符交换
*/在将nums加入时候,需要做个判断是否已经存在。
class Solution {
/**
* @param nums: A list of integers.
* @return: A list of unique permutations.
*/
public ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
// write your code here
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
ArrayList<Integer> item = new ArrayList<>();
permuteUnique(nums, res, 0, nums.size()-1);
return res;
}
@SuppressWarnings("unchecked")
public void permuteUnique(ArrayList<Integer> nums,
ArrayList<ArrayList<Integer>> res, int s, int e) {
if (s == e) { // s=e 则将其加入res中
boolean flag = false; // res中是否存在tmp值的arraylist.
for (int i = 0; i < res.size(); i++) {
if (res.get(i).equals(nums)) {
flag = true;
break;
}
}
if (!flag) {
res.add((ArrayList<Integer>) nums.clone());
}
return;
} else {
for (int i = s; i < nums.size(); i++) {
swap(nums, s, i);
permuteUnique(nums, res, s + 1, e);
swap(nums, s, i);
}
}
}
public void swap(ArrayList<Integer> nums, int s, int e) {
int tmp1 = nums.get(s);
int tmp2 = nums.get(e);
nums.set(s, tmp2);
nums.set(e, tmp1);
}
}