LeetCode题练习与总结:全排列Ⅱ

一、题目描述

给定一个可包含重复数字的序列 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

二、解题思路

  1. 对数组nums进行排序,这样相同的数字会相邻。
  2. 使用回溯算法生成所有可能的排列。
  3. 在选择数字时,如果当前数字与前一个数字相同,并且当前数字尚未被使用(used[i]false),则跳过这个数字,以避免重复。
  4. 使用一个布尔数组used来跟踪每个数字是否已经被选择过。

三、具体代码

import java.util.ArrayList;
import java.util.List;public class Solution {public List<List<Integer>> permuteUnique(int[] nums) {List<List<Integer>> results = new ArrayList<>();if (nums == null || nums.length == 0) {return results;}// 对数组进行排序,以便相同的数字相邻Arrays.sort(nums);boolean[] used = new boolean[nums.length]; // 用于跟踪数字是否已选择backtrack(new ArrayList<>(), nums, used, results);return results;}private void backtrack(List<Integer> current, int[] nums, boolean[] used, List<List<Integer>> results) {if (current.size() == nums.length) {// 当前排列长度等于nums长度时,表示找到了一个完整的排列results.add(new ArrayList<>(current));return;}for (int i = 0; i < nums.length; i++) {if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) {// 如果当前数字已使用,或者当前数字与前一个数字相同且前一个数字未被使用,则跳过continue;}// 选择当前数字,并将其标记为已使用current.add(nums[i]);used[i] = true;// 递归地构建下一个排列backtrack(current, nums, used, results);// 回溯,移除最后一个元素,并将其标记为未使用current.remove(current.size() - 1);used[i] = false;}}
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 首先,我们需要生成所有可能的排列。对于一个包含n个元素的数组,全排列的数量是n的阶乘(n!)。因此,最坏情况下,我们需要生成n!个排列。
  • 然而,由于数组中可能存在重复的元素,实际上生成的排列数量会少于n!。但是,我们无法精确地计算节省了多少时间,因为这取决于数组中重复元素的数量和分布。
  • 对于每个排列,我们需要遍历数组来选择下一个元素,这需要O(n)的时间。
  • 由于我们使用了回溯算法,每次递归调用都会生成一个新的数组来存储当前的排列,这意味着我们需要O(n)的空间来存储当前排列。
  • 综合考虑,时间复杂度为O(n * n!),这是因为我们需要对每个排列进行O(n)的操作。但是,由于重复元素的存在,实际的时间复杂度可能会低于这个理论值。
2. 空间复杂度
  • 我们使用了一个数组used来跟踪每个元素是否已经被使用,这个数组的大小与输入数组nums的大小相同,因此是O(n)。
  • 在递归过程中,我们需要额外的空间来存储当前的排列。在最坏的情况下,我们可能需要存储n个元素的排列,因此这部分的空间复杂度也是O(n)。
  • 由于递归调用的深度最多是n,因此总的空间复杂度是O(n)。

五、总结知识点

1. 数组排序 (Arrays.sort(nums)):

  • 使用Java标准库中的Arrays.sort方法对输入数组进行排序。这有助于将相同的元素放在一起,从而在生成排列时避免重复。

2. 回溯算法:

  • 回溯算法是一种通过递归来遍历所有可能情况的算法。在这个问题中,它用于生成所有可能的排列。
  • 回溯算法的关键是在适当的时机返回,以避免走进无效的路径(即生成重复的排列)。

3. 位掩码 (使用boolean[] used数组):

  • 位掩码是一种使用数组来跟踪状态的技术。在这个例子中,used数组用于跟踪哪些数字已经被添加到当前的排列中。
  • 通过检查used[i]的值,我们可以知道是否应该选择数组中索引为i的元素。

4. 递归:

  • 递归是一种通过函数自己调用自己来重复执行代码的方式。在这个例子中,backtrack方法递归地调用自己来构建新的排列。

5. 剪枝优化 (跳过重复元素):

  • 为了提高效率,我们在选择下一个元素时会检查当前元素是否与前一个已选择的元素相同,并且前一个元素是否已经被使用。如果这两个条件都满足,我们就跳过当前元素,这被称为剪枝优化。

6. List的操作 (ArrayList):

  • 使用ArrayList来存储当前的排列和最终的结果。ArrayList提供了动态数组的功能,允许我们在运行时添加和删除元素。

7. 深拷贝 (new ArrayList<>(current)):

  • 当我们将当前排列添加到结果列表时,我们使用深拷贝的方式创建一个新的ArrayList实例,以避免修改原始current列表时影响到结果。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/773283.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA使用常用的设置

一、IDEA常用设置 可参考&#xff1a;IDEA这样配置太香了_哔哩哔哩_bilibili 波波老师 二、插件 可参考&#xff1a;IDEA好用插件&#xff0c;强烈推荐_哔哩哔哩_bilibili 波波老师 三、其他 学会用点“.” IDEA弹窗Servers certificate is not trusted怎么禁止&#xf…

QEMU安装和使用@Ubuntu(待续)

参考这篇文档&#xff1a;在 QEMU 上运行 RISC-V 64 位版本的 Linux - 知乎 参考官方文档&#xff1a;Running 64- and 32-bit RISC-V Linux on QEMU — RISC-V - Getting Started Guide FreeBSD riscv下载&#xff1a;Index of /freebsd/releases/riscv/14.0-RELEASE/ Linux…

共享旅游卡到底是怎么回事?

共享旅游卡&#xff0c;一种引领旅游新风尚的智能卡片&#xff0c;正以其独特的方式改变着人们的旅游体验。千益畅行旅游卡&#xff0c;作为共享旅游卡的杰出代表&#xff0c;正逐渐成为旅游市场的新宠。 那么&#xff0c;共享旅游卡到底是什么&#xff1f;它又如何改变了我们…

计算机视觉之三维重建(4)---三维重建基础与极几何

文章目录 一、三维重建基础1.1 问题引入1.2 线性解法1.3 非线性解法1.4 多视图几何的关键问题 二、极几何与基础矩阵2.1 极几何2.2 极几何特例2.3 本质矩阵2.4 本质矩阵的性质2.5 基础矩阵2.6 基础矩阵的性质 三、基础矩阵估计 一、三维重建基础 1.1 问题引入 1. 从单张图像恢…

ROS机器人入门第四课:话题通信

文章目录 ROS机器人入门第四课&#xff1a;话题通信一、话题通信概述&#xff08;一&#xff09;概念&#xff08;二&#xff09;作用 二、话题通信基本操作需求:分析:流程:&#xff08;一&#xff09;发布方解释一些关键的ROS函数和概念&#xff1a; &#xff08;二&#xff0…

久菜盒子|医学大数据|R|常用安装包及介绍

复习下&#xff1a; library(tibble) library(readxl) library(survival) library(survminer) library(rms) library(forestplot) library(magrittr) library(corrplot) library(car) require(stringdist) library(timeROC) library(tidyverse) library(dplyr) library(tidyr)…

RESTful API 名词解释:查询参数、请求体参数、响应参数、内容类型(Content-Type)、表单

查询参数 RESTful API 设计中的查询参数 在 RESTful API 设计中&#xff0c;查询参数是什么意思&#xff1f; 在RESTful API设计中&#xff0c;查询参数是指当客户端发起GET请求以获取资源时附加在URL末尾的一部分&#xff0c;用来进一步筛选或定制返回资源的内容。查询参数通…

QT+Opencv+yolov5实现监测

功能说明&#xff1a;使用QTOpencvyolov5实现监测 仓库链接&#xff1a;https://gitee.com/wangyoujie11/qt_yolov5.git git本仓库到本地 一、环境配置 1.opencv配置 将OpenCV-MinGW-Build-OpenCV-4.5.2-x64文件夹放在自己的一个目录下&#xff0c;如我的路径&#xff1a; …

Android密钥库(AndroidKeyStore)使用

一、KeyStore描述 在 Android 开发中&#xff0c;KeyStore 是一个用于存储密钥和证书的安全容器。它提供了一种安全的方式来存储敏感信息&#xff0c;如密钥对、数字证书等&#xff0c;以防止它们被未授权的应用或攻击者访问。 KeyStore 通常用于加密数据、数字签名、TLS/SSL…

Spark SQL— Catalyst 优化器

Spark SQL— Catalyst 优化器 1. 目的 本文的目标是描述Spark SQL 优化框架以及它如何允许开发人员用很少的代码行表达复杂的查询转换。我们还将描述Spark SQL如何通过大幅提高其查询优化能力来提高查询的执行时间。在本教程中&#xff0c;我们还将介绍什么是优化、为什么使用…

蓝桥杯练习系统(算法训练)ALGO-967 共线

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 给定2维平面上n个整点的坐标&#xff0c;一条直线最多能过几个点&#xff1f; 输入格式 第一行一个整数n表示点的个数   …

【Django】枚举类型数据

模型 在模型里主要增加两项内容&#xff1a; 枚举表字段增加choices class Snort(CoreModel):PAGE_TYPE_CHOICES [(1, 失陷主机检测), # 1是保存到数据库里的数据&#xff0c;失陷主机检测是显示在前端的(2, 远程漏洞攻击检测),(3, 可疑流量行为),(4, WEB检测),]page_type…

STM32 使用gcc编译介绍

文章目录 前言1. keil5下的默认编译工具链用的是哪个2. Arm编译工具链和GCC编译工具链有什么区别吗&#xff1f;3. Gcc交叉编译工具链的命名规范4. 怎么下载gcc-arm编译工具链参考资料 前言 我们在STM32上进行开发时&#xff0c;一般都是基于Keil5进行编译下载&#xff0c;Kei…

React中的受控组件与非受控组件

受控组件与非受控组件 受控组件 组件(input, select)的状态与state的值绑定&#xff0c;组件的状态全程响应外部数据 class TestComponent extends React.Component {constructor (props) {super(props);this.state { username: lindaidai };}render () {return <input …

区块链安全之DDoS防护的重要性及其实施策略

随着区块链技术的不断发展和广泛应用&#xff0c;其安全问题也日益凸显。其中&#xff0c;分布式拒绝服务(DDoS)攻击是对区块链网络稳定性和效率构成潜在威胁的重要因素之一。本文旨在深入探讨区块链为何需要采取DDoS高防措施&#xff0c;并提出相应的防护策略。 一、区块链面…

博客系统——3、数据库表设计 - 博客标签表

任务描述 本关任务&#xff1a;在博客数据库中建立博客标签表。 相关知识 多对多关系的建立 每一个博客都可以设置很多个标签&#xff0c;比如一篇讲JavaWeb知识的博客&#xff0c;就可能会涉及到多个标签如&#xff1a;前端、后端、Java、SpringMVC等标签&#xff0c;而一…

碳课堂|什么是碳资产?企业如何进行碳资产管理?

碳资产是绿色资产的重要类别&#xff0c;在全球气候变化日益严峻的背景下备受关注。在“双碳”目标下&#xff0c;碳资产管理是企业层面实现碳减排目标和低碳转型的关键。 一、什么是碳资产&#xff1f; 碳资产是以碳减排为基础的资产&#xff0c;是企业为了积极应对气候变化&…

Kubernetes示例yaml:1. service-deployment.yaml

service-deployment.yaml 示例 apiVersion: apps/v1 kind: Deployment metadata:name: example-plusnamespace: aaaalabels:app: example-prdapp_unit: AAAA-EXAMPLE spec:replicas: 2selector:matchLabels:app: example-prdtemplate:metadata:labels:app: example-prdapp_uni…

js相关的dom方法

查找元素 //获取元素id为box的元素 document.getElementById(box) //获取元素类名为box的元素 document.getElementsByClassName(box) //获取标签名为div的元素 document.getElementsByTagName(div)改变元素 //设置id为box的元素内容 document.getElementById("box"…

常见位运算的总结

目录 一、基础位运算 二、给一个数n&#xff0c;确定它的二进制中的第x位是0还是1 三、将一个数n的二进制表示的第x位修改成1 四、将一个数n的二进制位表示的第x位修改成0 五、位图思想 六、提取一个数(n)二进制表示中最右侧的1(lowbit) 七、干掉一个数n的最右侧的1 八、…