LeetCode:全排列II【47】
LeetCode:全排列II【47】
参考自天码营题解:https://www.tianmaying.com/tutorial/LC47
题目描述
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
题目分析
这道题与上一道全排列I的区别在于,这一次给的序列可以包含重复元素。
1、那此时我们怎么判断当前元素是否使用过呢?
我们使用BitMap(位图)技术建立一个和序列长度相等的布尔数组,记录每一个位置的元素是否使用过就可以了。这样,无疑会遍历到每一个不同的排列,但是也存在着问题,以样例为例,[1,1,2]这样的排列会被遍历到许多次,这就导致最后输出的答案存在着重复。
2、如何解决这样的重复呢?
我们先看看这样的重复是如何产生的,不难发现,[1,1,2]在之前描述的回溯中会枚举2次。如果不用数值而是用这个数在nums中的下标来表示的话,[1,1,2]被枚举的两次分别是[0,1,2]和[1,0,2],即下标为0的“1”和下标为1的“1”在枚举的过程中被考虑成了两个不同的选择,但是在最后的答案中却没有什么不同。
而这样产生的重复也非常好解决,就是对于一个位置的同一个取值,只枚举一次,也就是如果已经在第1个位置上枚举了“1”这个数字,那么即使之后仍然有“1”的取值,也都跳过不进行枚举。
在实际的实现中,我们不妨这样枚举,即将nums数组排序后,只有nums[i]不等于nums[i-1]时,才将nums[i]视作一种可能的取值,即:
for (int i = 0; i < nums.size(); i++) {
// 确保在一个位置不会枚举两个相同的数
if (i == nums.size() - 1 || nums[i] != nums[i-1]) {
}
}
这样,就可以保证[1,1,2]在最终的方案中只被计算一次,即同一个取值的元素只取最左边的。

特别的,当加入了used[]数组用于判断一个数字是否被使用过之后,由于每次使用的一定是所有相同数字中最左侧的一个,所以对于一个取值,如果它左侧的数字是已经被使用过了的,就同样说明这个数是当前所有相同数字中最左侧的可用的了,即:
for (int i = 0; i < nums.size(); i++) if (!used[i]) {
// 确保在一个位置不会枚举两个相同的数
if (i == nums.size() - 1 || nums[i] != nums[i - 1] || used[i - 1]) {
}
}
我的解法比较简单,没有利用排序,也没有跳过策略,只是在最后放入结果集的时候,检测是否有排列的元素出现过,这将会导致很多无意义的递归过程。
高效解法
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, boolean [] used){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;
used[i] = true;
tempList.add(nums[i]);
backtrack(list, tempList, nums, used);
used[i] = false;
tempList.remove(tempList.size() - 1);
}
}
}
Java题解
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
backtrack(lists,new ArrayList<>(),new boolean[nums.length],nums);
return lists;
}
public void backtrack(List<List<Integer>> lists,List<Integer> tmpList,boolean[] visited,int[] nums)
{
if(tmpList.size()==nums.length&&!lists.contains(tmpList))
lists.add(new ArrayList<>(tmpList));
else
for(int i=0;i<nums.length;i++)
{
if(visited[i])
continue;
visited[i]=true;
tmpList.add(nums[i]);
backtrack(lists,tmpList,visited, nums);
visited[i]=false;
tmpList.remove(tmpList.size()-1);
}
}
}
LeetCode:全排列II【47】的更多相关文章
- Leetcode之回溯法专题-47. 全排列 II(Permutations II)
Leetcode之回溯法专题-47. 全排列 II(Permutations II) 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2] ...
- [LeetCode] 47. 全排列 II
题目链接 : https://leetcode-cn.com/problems/permutations-ii/ 题目描述: 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [ ...
- Java实现 LeetCode 47 全排列 II(二)
47. 全排列 II 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ] class Solut ...
- leetcode 46. 全排列 及 47. 全排列 II
46. 全排列 问题描述 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3 ...
- [LeetCode] 267. Palindrome Permutation II 回文全排列 II
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- leetcode Permutations II 无重全排列
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4051169.html 题目链接:leetcode Permutations II 无重全排 ...
- 47. 全排列 II
47. 全排列 II 题意 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2]输出:[ [1,1,2], [1,2,1], [2,1,1]] 解题思路 去重的全排列 ...
- [LeetCode] 47. Permutations II 全排列 II
Given a collection of numbers that might contain duplicates, return all possible unique permutations ...
- LeetCode 47——全排列 II
1. 题目 2. 解答 在 LeetCode 46--全排列 中我们已经知道,全排列其实就是先确定某一个位置的元素,然后余下就是一个子问题.在那个问题中,数据没有重复,所以数据中的任意元素都可以放在最 ...
随机推荐
- 【Mac + Python3.6 + ATX基于facebook-wda】之IOS自动化(三):facebook-wda库--API学习以及附录:Github上对WDA的问题解答
下面简单介绍facebook-wda库--API的学习 import wda # debug模式,会在run运行时控制台生成消息 wda.DEBUG = False # False 关闭,True开启 ...
- Java多线程基础知识总结
2016-07-18 15:40:51 Java 多线程基础 1. 线程和进程 1.1 进程的概念 进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程, ...
- 【BZOJ】2100: [Usaco2010 Dec]Apple Delivery(spfa+优化)
http://www.lydsy.com/JudgeOnline/problem.php?id=2100 这题我要吐血啊 我交了不下10次tle.. 噗 果然是写挫了. 一开始没加spfa优化果断t ...
- 修改原型给数组对象添加forEach
Array.prototype.forEach = function (callback, context) { for (var i = 0; i < this.length; i++) { ...
- http文件导出
using (MemoryStream file = db.ExportExcel(model)) { context.Response.ContentType = "application ...
- (转)servlet setCharacterEncoding setContentType
转自:http://blog.csdn.net/fancylovejava/article/details/7700683 编码中的setCharacterEncoding 理解 1.pageEnco ...
- Material design之Compatibility(适配)
Compatibility,为Android L版本和旧版本进行适配设置. 一:Material Theme适配 因为Material Theme只能在Android L的版本中使用,所以为了应用能在 ...
- poj 3310(并查集判环,图的连通性,树上最长直径路径标记)
题目链接:http://poj.org/problem?id=3310 思路:首先是判断图的连通性,以及是否有环存在,这里我们可以用并查集判断,然后就是找2次dfs找树上最长直径了,并且对树上最长直径 ...
- Android开发:《Gradle Recipes for Android》阅读笔记(翻译)4.5——使用Android Libraries
问题: 你想要在app当中增加新的library模块 解决方案: 使用library插件,增加一个library模块作为依赖. 讨论: 不可以通过使用java库给app增加许多功能,通常是使用jar包 ...
- iOS-将NSString转换成UTF8编码的NSString
在使用网络地址时,一般要先将url进行encode成UTF8格式的编码,否则在使用时可能报告网址不存在的错误,这时就需要进行转换 下面就是转换函数: NSString *urlString= [NSS ...