47. 全排列 II
创始人
2024-03-17 01:13:23

关上过去和未来的铁门,活在“今天”这个舱室中。                                 ——《人性的优点》

47. 全排列 II

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]

示例 2:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

提示:

1 <= nums.length <= 8
-10 <= nums[i] <= 10

思路:(回溯)

此题是 46. 全排列 的进阶

  • 但是这道题有了一点改变,那么就是列表里面有重复数字,全排列的结果,相同答案只算一种,那么我们就要考虑重复。
  • 当然因为题目没有说该队列有序,所以要先排序。

判断的时候加上:

if(i > 0 && nums[i] == nums[i-1] && hasVisited[i-1] == false) {continue;
}

其中最为关键的是 hasVisited[i-1] == false ,用来去重,就是限制一下两个相邻的重复的访问顺序

举个栗子 :

对于两个相同的数 1 1 ,我们将其命名为 a b,a 表示第一个 1 ,b 表示第二个 1

  • 如果不去重得的话,会有两种重复排列 a b,b a ,我们只需取其中任意一种排列即可;
  • 为了达到目的,限制一下 a ,b 的访问顺序即可;
  • 比如 我们只取 a b 这个排列的话,只有当 nums[i - 1] 访问后,我们才去访问 nums[i] ,
  • 也就是说 如果 hasVisited[i-1] == false 的话, 则 continue 跳过。

举另个栗子 :

去重最为关键的代码为:

if(i > 0 && nums[i] == nums[i-1] && hasVisited[i-1] == false) {continue;
}

但如果改成 hasVisited[i-1] == true ,也是正确的, 去重代码如下:

if(i > 0 && nums[i] == nums[i-1] && hasVisited[i-1] == true) {continue;
}

这是为什么呢?

  • hasVisited[i-1] == false ,是对树层中前一位去重;
  • hasVisited[i-1] == true ,是对树枝前一位去重;

(借用一下别人的图进行理解):

如果 是三个相同的数 1 1 1

树层上去重(hasVisited[i-1] == false),树形结构如下:
在这里插入图片描述
树枝上去重(hasVisited[i-1] == true),树形结构如下:
在这里插入图片描述
观察上图可以得出:

  • 树层上对前一位去重非常彻底,效率很高;
  • 树枝上对前一位去重虽然最后可以得到答案,但是做了很多无用搜索。

代码:(Java)

import java.util.ArrayList;
import java.util.List;public class all_permute {public static void main(String[] args) {// TODO 自动生成的方法存根int [] nums = {1, 1, 2};System.out.println(permuteUnique(nums));}public static List> permuteUnique(int[] nums) {List> permutes = new ArrayList<>();List permute = new ArrayList<>();if(nums == null || nums.length == 0) {return permutes;}int flag = 0;//标记for(int i = 1; i < nums.length ; i++) {//冒泡排序for(int j = 0; j < nums.length - i; j++) {if(nums[j] > nums[j+1]) {int temp = nums[j];nums[j] = nums[j+1];nums[j+1] = temp;flag++;}}if(flag == 0)break;}boolean [] hasVisited = new boolean[nums.length];backTracking(nums, hasVisited, permute, permutes);return permutes;}private static void backTracking(int[] nums, boolean[] hasVisited, List permute, List> permutes) {// TODO 自动生成的方法存根if(permute.size() == hasVisited.length) {permutes.add(new ArrayList<>(permute));return;}for(int i = 0; i < nums.length; i++) {if(hasVisited[i]) {continue;}if(i > 0 && nums[i] == nums[i-1] && hasVisited[i-1] == false) {continue;}hasVisited[i] = true;permute.add(nums[i]);backTracking(nums, hasVisited, permute, permutes);permute.remove(permute.size() - 1);hasVisited[i] = false;}}
}

运行结果:

在这里插入图片描述

复杂度分析:

  • 时间复杂度:O(n×n!)O(n×n!)O(n×n!),其中 n 为序列的长度。

    • 算法的复杂度首先受 backTracking 的调用次数制约,backTracking 的调用次数为∑k=1nP(n,k)\sum_{k=1}^{n} P(n, k)∑k=1n​P(n,k)次,其中 P(n,k)=n!(n−k)!=n(n−1)…(n−k+1)P(n, k)=\frac{n !}{(n-k) !}=n(n-1) \ldots(n-k+1)P(n,k)=(n−k)!n!​=n(n−1)…(n−k+1),该式被称作 n 的 k - 排列,或者部分排列。

    • 而 ∑k=1nP(n,k)=n!+n!1!+n!2!+n!3!+…+n!(n−1)!<2n!+n!2+n!22+n!2n2<3n!\sum_{k=1}^{n} P(n, k)=n !+\frac{n !}{1 !}+\frac{n !}{2 !}+\frac{n !}{3 !}+\ldots+\frac{n !}{(n-1) !}<2 n !+\frac{n !}{2}+\frac{n !}{2^{2}}+\frac{n !}{2^{n} 2}<3 n !∑k=1n​P(n,k)=n!+1!n!​+2!n!​+3!n!​+…+(n−1)!n!​<2n!+2n!​+22n!​+2n2n!​<3n!
      , 这说明 backTracking 的调用次数是 O(n!)O(n!)O(n!)的。

    • 而对于 backTracking调用的每个叶结点(最坏情况下没有重复数字共 n!n!n!个),我们需要将当前答案使用 O(n)O(n)O(n)的时间复制到答案数组中,相乘得时间复杂度为 O(n×n!)O(n×n!)O(n×n!)。

    • 因此时间复杂度为O(n×n!)O(n×n!)O(n×n!)。

  • 空间复杂度:O(n)O(n)O(n)。我们需要O(n)O(n)O(n)的标记数组,同时在递归的时候栈深度会达到O(n)O(n)O(n),因此总空间复杂度为 O(n+n)=O(2n)=O(n)O(n+n)=O(2n)=O(n)O(n+n)=O(2n)=O(n)。

注:仅供学习参考!

题目来源:力扣

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...