PermutationTwo
Description:
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]
] Thoughts:
这个问题和之前的permutations问题类似,区别在于这次给定的数字有重复的部分,但是我们输出的排列又不允许重复。排列的话,一个数字不允许重复使用,之前在permutions中我们用Nums.contains来规避这个问题,但是在现在这个问题中因为
nums中有重复的数字,所以这个方法不行了,解决的办法是我们开辟一个和nums等长的boolean数组addnums,addnums中值为true,表示nums中对应位置上的数字已经被包含在排列中,就要跳过这个数字。通过这个方法我们就解决了基本的排列问题。
还有一个问题需要解决的就是排列不允许重复,这个问题的解决方法就是跳过那些已经作为首数字出现过的数字。首先我们对于原始数组进行一次排序,然后在每次选择数字的时候判断,对于大于首字符的数字是否等于首字符,并且还没有使用过,
如果是的话就跳过。以下是我的java代码:
package middle;
import java.util.*;
public class PermutationTwo {
public List<List<Integer>> permuteUnique(int[] nums){
List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums);
ArrayList addnums = new ArrayList();
trackBack(nums, new ArrayList(), result, addnums);
return result;
} private void trackBack(int[] nums, ArrayList arrayList,
List<List<Integer>> result, ArrayList addnums) {
// TODO Auto-generated method stub
if(arrayList.size()==nums.length && result.contains(arrayList)==false){
result.add(new ArrayList(arrayList));
}
for(int i = 0; i<nums.length;i++){
// if(i > 0 && nums[i] == nums[i-1]) continue;
if(addnums.contains(i)) continue;
arrayList.add(nums[i]);
addnums.add(i);
trackBack(nums, arrayList, result, addnums);
arrayList.remove(arrayList.size() - 1);
addnums.remove(addnums.size() - 1);
}
} public List<List<Integer>> permuteUniqueTwo(int[] nums){
List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums);
trackBackTwo(nums, result, new ArrayList(), new boolean[nums.length]); return result;
} private void trackBackTwo(int[] nums, List<List<Integer>> result,
ArrayList arrayList, boolean[] use) {
// TODO Auto-generated method stub
if(arrayList.size() == nums.length){
result.add(new ArrayList(arrayList));
}else{
for(int i = 0; i< nums.length;i++){
if(use[i] || i > 0&&nums[i] == nums[i-1]&&use[i-1]==false) continue;
use[i] = true;
arrayList.add(nums[i]);
trackBackTwo(nums, result, arrayList, use);
arrayList.remove(arrayList.size() - 1);
use[i] = false;
}
}
} public static void main(String args[]){
PermutationTwo p = new PermutationTwo();
int[] nums = new int[]{1, -1, 1, 2, -1, 2, 2, -1};
List<List<Integer>> list = p.permuteUniqueTwo(nums);
System.out.println(list);
} }
还有第二种更加直观的解法,但是它的执行时间太慢了,leetcode上通过不了,但是为了更加便于理解我还是把它写出来。解决重复数字的问题,我是用一个ArrayList记录当前已经使用过的数字的位置,如果当前数字的位置在ArrayList中已经
出现过了,那就说明当前的数字已经用过了,就要跳过。然后我们根据得到的排列,判断当前的排列是否包含在result中,如果包含了,也就是说当前的排列已经出现过了,那么该排列就不能加入到result中。换句话说,只有新的排列才能够出现在result
中。以下是我的java代码:
package middle;
import java.util.*;
public class PermutationTwo {
public List<List<Integer>> permuteUnique(int[] nums){
List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums);
ArrayList addnums = new ArrayList();
trackBack(nums, new ArrayList(), result, addnums);
return result;
} private void trackBack(int[] nums, ArrayList arrayList,
List<List<Integer>> result, ArrayList addnums) {
// TODO Auto-generated method stub
if(arrayList.size()==nums.length && result.contains(arrayList)==false){
result.add(new ArrayList(arrayList));
}
for(int i = 0; i<nums.length;i++){
// if(i > 0 && nums[i] == nums[i-1]) continue;
if(addnums.contains(i)) continue;
arrayList.add(nums[i]);
addnums.add(i);
trackBack(nums, arrayList, result, addnums);
arrayList.remove(arrayList.size() - 1);
addnums.remove(addnums.size() - 1);
}
} public static void main(String args[]){
PermutationTwo p = new PermutationTwo();
int[] nums = new int[]{1, -1, 1, 2, -1, 2, 2, -1};
List<List<Integer>> list = p.permuteUnique(nums);
System.out.println(list);
} }
PermutationTwo的更多相关文章
随机推荐
- STL:set/multiset用法详解
集合 使用set或multiset之前,必须加入头文件<set> Set.multiset都是集合类,差别在与set中不允许有重复元素,multiset中允许有重复元素. sets和mul ...
- android binder理解
Android中的Parcel是什么 Parcel,翻译过来是"打包"的意思.打包干什么呢?是为了序列化. 如果要在进程之间传递一个整数,很简单,直接传就是行了:如果要传 ...
- (五十一)KVC与KVO详解
KVC的全称为key value coding,它是一种使用字符串间接更改对象属性的方法. 假设有一个Person类和一个Student类,其中Person类有age.name两个属性,Student ...
- 使用OC和Swift两种语言写一个发射烟花的小项目
OC与Swift两种实现方式基本上区别不大,主要是在一些对象或方法的调用方式不同,附带源码. OC代码样式: self.view.backgroundColor = [UIColor blackCol ...
- 关于JavaScript中的几种匿名行数的写法
匿名函数没有实际名字,也没有指针,怎么执行滴? 其实大家可以看看小括号的意义就应该可以理解.小括号有返回值,也就是小括号内的函数或者表达式的返回值,所以说小括号内的function返回值等于小括 ...
- JavaScript进阶(三)常见工具(校验、通用)
JS常见工具(校验.通用) // 姓名校验 var checkName = function(name) { // 收货人姓名校验(准则:姓名为2-4汉字) var regu = /^[\u4E00- ...
- 【一天一道LeetCode】#15 3Sum
一天一道LeetCode系列 (一)题目 Given an array S of n integers, are there elements a, b, c in S such that a + b ...
- cocos2d-x 读写 xml 文件
cocos2d-x 读写 xml 文件 A product of cheungmine使用cocos2d-x开发2d游戏确实方便,但是对于一般的小游戏,经常需要的工作是UI布局设计和调整,代码改来改去 ...
- 【51】java设计模式-工厂设计模式剖析
工厂设计设计模式的分类: 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Factory):不利于产生系列产品: 2)工厂方法模式(Factory Method) ...
- linu下C语言之BMP图片操作编程(上)
BMP文件格式,也被称为位图图像文件或与设备无关的位图文件格式(DIB)或者只是一个位图,是 一个光栅图形 图像文件格式使用 来存储位图,数字,图片,独立的显示设备. 微软已经定义了一个特定的表示颜色 ...