您的位置:首页 > 其它

[leetcode]Permutations II

2013-09-21 11:57 393 查看
要完成这道题,首先让我们再回顾一下SubSet II http://discuss.leetcode.com/questions/265/subsets-ii

1.每次进入sub的时候,都会记录当前path为一个结果(一个子集);
2.进入sub时,是用i个元素的子集来推导i+1个元素的子集的过程;
3.有了i个元素,第i+1个元素只从原始集合S的位置i之后的元素选;
4.该算法的关键是,有序添加。保证,产生的集合中的元素是有序的。
比如[1,2,3,4,5](暂不考虑重复)
如果进入sub的时候是[1,3],那么下一步是[1,3,4]和[1,3,5]
为什么没有[1,3,2]呢,因为[1,2]比如在[1,3]之前处理过了,它会处理到[1,2,3]的;
5.因为有序,那么已取的i个元素的集合中的最后一个元素,是一个分界。可以用它来判重。

/article/6713566.html

但对Permutation来说,本来就是尝试不同的顺序,没有有序这个概念,怎么弄呢?

答案是,递归时采用完全不同的方法。(上面这个方法,可能主要对求子集适用。)但在关键的判重部分,对重复的元素采用有序的思想。

例如:
输入为1 1 2,只要保证最后生成的组合中第二个1依旧在第一个1之后,就能保证不会出现重复的组合。
1 1 2,标记为1(1) 1(2) 2,它们能生成的所有组合
去掉1(2)在1(1)之前的情况:
1(1) 1(2) 2
1(1) 2 1(2)
2 1(1) 1(2)
即为所求。

方法采用的是:http://www.cnblogs.com/remlostime/archive/2012/11/13/2768816.html

先对数组进行排序,这样在DFS的时候,可以先判断前面的一个数是否和自己相等,相等的时候则前面的数必须使用了,自己才能使用,这样就不会产生重复的排列了。

最后,莫忘一开始排个序。还有将tmp添加到result里时要new一份,否则后面会被清空。

public class Solution {
ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> tmp = new ArrayList<Integer>();
public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
ans.clear();
tmp.clear();
Arrays.sort(num);
int len = num.length;
boolean[] canUse = new boolean[len];
for (int i = 0; i < len; i++)
{
canUse[i] = true;
}
sub(num, canUse);
return ans;
}

private void sub(int[] num, boolean[] canUse)
{
if (tmp.size() == num.length)
{
ans.add(new ArrayList<Integer>(tmp));
}
else
{
for (int i = 0; i < num.length; i++)
{
if (canUse[i])
{
if (i!=0 && num[i] == num[i-1] && canUse[i-1]) continue;
tmp.add(num[i]);
canUse[i] = false;
sub(num, canUse);
tmp.remove(tmp.size()-1);
canUse[i] = true;
}
}
}
}
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: