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的更多相关文章
随机推荐
- Mybatis事务(一)事务管理方式
Mybatis管理事务是分为两种方式: (1)使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交 (2)使用MANAGED的事务管理机制,这种机制mybat ...
- Chapter 2 User Authentication, Authorization, and Security(1):选择Windows和SQL 身份验证
原文出处:http://blog.csdn.net/dba_huangzj/article/details/38657111,专题目录:http://blog.csdn.net/dba_huangzj ...
- Visual Studio2010 安装pthreads2.9.1
本人最近要利用多线程进行编程,前面一篇博文讲解的是利用VC自带的一些函数库,这里重点探讨一下如何配置pthreads2.9.1的Visual Studio2010的环境.本文分为两个部分,第一部分给出 ...
- [Java]数组排序-选择排序 冒泡排序 插入排序
1 选择排序 原理:a 将数组中的每个元素,与第一个元素比较 如果这个元素小于第一个元素, 就将这个 两个元素交换. b 每轮使用a的规则, 可以选择出 ...
- 9、Libgdx的输入处理
(官网:www.libgdx.cn) 不同的平台有着不同的输入方式.桌面用户可以通过键盘和鼠标与应用进行交互,基于浏览器的游戏也是这样.在Android中,鼠标被触摸屏所替代,通常没有实体键盘.And ...
- 【Unity Shaders】Diffuse Shading——创建一个自定义的diffuse lighting model(漫反射光照模型)
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Unity 5.X扩展编辑器之打包assetbundle
5.x的assetbundle与4.x以及之前的版本有些不同,不过本质是一样的,只不过5.x打包assetbundle更为简单和人性化了,总体来说只需要三个步骤: 第一步:创建打包资源 //这里是一个 ...
- Android 上滑上拉菜单SlidingDrawer 不全屏显示的方法
这里来说一个已经被废弃的SlidingDrawer.. 他可以实现上拉,下拉的菜单. 但是有个问题就是上拉以后,是全屏显示的. 首先 写一个布局: <RelativeLayout xmlns:a ...
- Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型
Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...
- Android群英传笔记——第六章:Android绘图机制与处理技巧
Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...