您的位置:首页 > 编程语言 > Java开发

leetcode-47. Permutations II

2016-12-03 11:09 337 查看

leetcode-47. Permutations II

题目:

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,

[1,1,2] have the following unique permutations:

[

[1,1,2],

[1,2,1],

[2,1,1]

]

这题和前一题比较类似46题博客正好也跟我之前说的思路比较接近。

主要要解决两个问题:

第一个问题是如何排序,总的来说常规的思路,就是建一个list,然后不断的加不同位置的值进去。并且在不同的迭代层次插入和删除元素,完成回溯。这也是java比较好实现的一种典型的回溯法。但是就这题来说其实也可以使用交换数组中固定元素的方式来遍历。但是这里有个无关算法的小trick,就是Arrays.asList(int[])类型是不能添加到集合中的,因为返回的是
List<int[]>
,如果你希望int[]转换为collection的话要么先转换成Integer填完值,然后再用
collection.add(Arrays.asList<Integer[]>)
,要么你就重建个collection,然后依次把值填充进去,这是java的历史遗留问题。没办法。

第二个问题是如何解决重复问题。因为46题中是不重复的nums,这样只要判断list中释放包含当前位置的值就行,但是如果有重复值就没有办法使用这种方法判断,要判断是否重复,有两类比较简单的思路一类是使用boolean []来维护当前的位置释放被使用过,另一类是使用hashset。第一类比较好理解,就是跟着
list.add()和list.remove()
一起做操作。第二类有一个问题需要说明一下,我在使用hashset的方法的时候想法是把所有的排序都列出来然后添加到hashSet,然后再将set转换成list结果,且不说能不能实现。这种思路一个最大的弊病是必须将全部的搜索空间都搜索完才能知道那些是有用的结果。所以时间复杂度比较高。而正确的使用hashset的方式是在每一个迭代层次维护一个hashset,或者说每个最终在结果的第i位维护一个hashset。如果遇到重复的值则不需要搜索,这样hashset既可以防止重复的情况,也可以减少搜索空间。

解1来源

解2来源

类似解2的另一实现

public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ret = new ArrayList<List<Integer>>();
boolean[] used = new boolean [nums.length];
Arrays.sort(nums);
helper(ret,nums,new ArrayList<Integer>(),used);
return ret;
}

private void helper(List<List<Integer>> ret , int[] nums, List<Integer> list ,boolean[] used){
if(list.size()==nums.length){
ret.add(new ArrayList<Integer>(list));
return ;
}

for(int i = 0 ; i < nums.length ; i++){
if(used[i]) continue;
if(i>0 && nums[i]==nums[i-1] && !used[i-1]) continue;
list.add(nums[i]);
used[i]=true;
helper(ret,nums,list,used);
list.remove(list.size()-1);
used[i]=false;
}
}
}


public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
if (nums==null || nums.length==0) { return ans; }
permute(ans, nums, 0);
return ans;
}

private void permute(List<List<Integer>> ans, int[] nums, int index) {
if (index == nums.length) {
List<Integer> temp = new ArrayList<>();
for (int num: nums) { temp.add(num); }
ans.add(temp);
return;
}
Set<Integer> appeared = new HashSet<>();
for (int i=index; i<nums.length; ++i) {
if (appeared.add(nums[i])) {
swap(nums, index, i);
permute(ans, nums, index+1);
swap(nums, index, i);
}
}
}

private void swap(int[] nums, int i, int j) {
int save = nums[i];
nums[i] = nums[j];
nums[j] = save;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode java