LeetCode47

news2025/2/21 17:59:58

LeetCode47

目录

  • 题目描述
  • 示例
  • 思路分析
  • 代码段
  • 代码逐行讲解
  • 复杂度分析
  • 总结的知识点
  • 整合
  • 总结

题目描述

给定一个可包含重复数字的整数数组 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. 排序
    • 将数组排序,使相同的数字相邻,方便后续去重。
  2. 深度优先搜索(DFS)
    • 使用 DFS 遍历所有可能的排列。
  3. 剪枝
    • 在 DFS 过程中,如果当前数字与前一个数字相同,并且前一个数字未被使用,则跳过当前数字,避免重复排列。
  4. 回溯
    • 在 DFS 过程中,使用 visited 数组标记已使用的数字,并在回溯时取消标记。

代码段

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums); 
        List<List<Integer>> res = new ArrayList<>();
        dfs(nums, new boolean[nums.length], new LinkedList<>(), res); 
        return res;
    }

    private static void dfs(int[] nums, boolean[] visited, LinkedList<Integer> stack, List<List<Integer>> res) {
        if (stack.size() == nums.length) { 
            res.add(new ArrayList<>(stack));
            return;
        }

        for (int i = 0; i < nums.length; i++) {
 
            if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
                continue;
            }
            if (!visited[i]) { 
                stack.push(nums[i]); 
                visited[i] = true; 
                dfs(nums, visited, stack, res); 
                visited[i] = false; 
                stack.pop();
            }
        }
    }
}

在这里插入图片描述


代码逐行讲解

1. 排序

Arrays.sort(nums);
  • 将数组排序,使相同的数字相邻,方便后续去重。

2. 初始化结果列表

List<List<Integer>> res = new ArrayList<>();
  • res 用于存储所有不重复的排列。

3. 调用 DFS

dfs(nums, new boolean[nums.length], new LinkedList<>(), res);
  • 调用 DFS 函数,传入数组 numsvisited 数组(用于标记已使用的数字)、stack(用于存储当前排列)和结果列表 res

4. DFS 函数

private static void dfs(int[] nums, boolean[] visited, LinkedList<Integer> stack, List<List<Integer>> res) {
  • DFS 函数的定义,用于递归生成排列。

5. 找到一个排列

if (stack.size() == nums.length) {
    res.add(new ArrayList<>(stack));
    return;
}
  • 如果当前排列的长度等于数组长度,说明找到一个完整的排列,将其加入结果列表。

6. 遍历数组

for (int i = 0; i < nums.length; i++) {
  • 遍历数组中的每个数字,尝试将其加入当前排列。

7. 剪枝:避免重复排列

if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
    continue;
}
  • 如果当前数字与前一个数字相同,并且前一个数字未被使用,则跳过当前数字,避免重复排列。

8. 加入当前数字

if (!visited[i]) {
    stack.push(nums[i]);
    visited[i] = true;
  • 如果当前数字未被使用,将其加入当前排列,并标记为已使用。

9. 递归

dfs(nums, visited, stack, res);
  • 递归调用 DFS,继续生成下一个数字的排列。

10. 回溯

visited[i] = false;
stack.pop();
  • 回溯时取消当前数字的标记,并将其从当前排列中移除。

复杂度分析

时间复杂度

  • 全排列的数量为 O(n!),其中 n 是数组的长度。
  • 每次生成一个排列需要 O(n) 的时间。
  • 因此,总时间复杂度为 O(n * n!)

空间复杂度

  • 需要存储所有排列,空间复杂度为 O(n * n!)
  • 递归栈的深度为 n,因此额外空间复杂度为 O(n)

总结的知识点

1. 排序

  • 使用 Arrays.sort 对数组进行排序,方便后续去重。

2. 深度优先搜索(DFS)

  • 使用 DFS 遍历所有可能的排列。

3. 剪枝

  • 在 DFS 过程中,通过条件判断避免生成重复的排列。

4. 回溯

  • 在 DFS 过程中,使用 visited 数组标记已使用的数字,并在回溯时取消标记。

整合

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums); // 排序
        List<List<Integer>> res = new ArrayList<>(); // 结果列表
        dfs(nums, new boolean[nums.length], new LinkedList<>(), res); // DFS
        return res;
    }

    private static void dfs(int[] nums, boolean[] visited, LinkedList<Integer> stack, List<List<Integer>> res) {
        if (stack.size() == nums.length) { // 找到一个排列
            res.add(new ArrayList<>(stack));
            return;
        }
        // 遍历 nums 数组
        for (int i = 0; i < nums.length; i++) {
            // 剪枝:避免重复排列
            if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
                continue;
            }
            if (!visited[i]) { // 如果当前数字未被使用
                stack.push(nums[i]); // 加入当前排列
                visited[i] = true; // 标记为已使用
                dfs(nums, visited, stack, res); // 递归
                visited[i] = false; // 回溯
                stack.pop(); // 移除当前数字
            }
        }
    }
}

总结

这段代码通过排序、DFS 和剪枝,能够高效地生成所有不重复的全排列。

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

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

相关文章

【Unity动画】导入动画资源到项目中,Animator播放角色动画片段,角色会跟随着动画播放移动。

导入动画资源到项目中&#xff0c;Animator播放角色动画片段,角色会跟随着动画播放移动&#xff0c;但我只想要角色在原地播放动画。比如&#xff1a;播放一个角色Run动画&#xff0c;希望角色在原地奔跑&#xff0c;而不是产生了移动距离。 问题排查&#xff1a; 1.是否勾选…

图解循环神经网络(RNN)

目录 1.循环神经网络介绍 2.网络结构 3.结构分类 4.模型工作原理 5.模型工作示例 6.总结 1.循环神经网络介绍 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种专门用于处理序列数据的神经网络结构。与传统的神经网络不同&#xff0c…

【数据结构】(9) 优先级队列(堆)

一、优先级队列 优先级队列不同于队列&#xff0c;队列是先进先出&#xff0c;优先级队列是优先级最高的先出。一般有两种操作&#xff1a;返回最高优先级对象&#xff0c;添加一个新对象。 二、堆 2.1、什么是堆 堆也是一种数据结构&#xff0c;是一棵完全二叉树&#xff0c…

4、IP查找工具-Angry IP Scanner

在前序文章中&#xff0c;提到了多种IP查找方法&#xff0c;可能回存在不同场景需要使用不同的查找命令&#xff0c;有些不容易记忆&#xff0c;本文将介绍一个比较优秀的IP查找工具&#xff0c;可以应用在连接树莓派或查找IP的其他场景中。供大家参考。 Angry IP Scanner下载…

【Linux】命令操作、打jar包、项目部署

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;Xshell下载 1&#xff1a;镜像设置 二&#xff1a;阿里云设置镜像Ubuntu 三&#xf…

瑞萨RA-T系列芯片ADCGPT功能模块的配合使用

在马达或电源工程中&#xff0c;往往需要采集多路AD信号&#xff0c;且这些信号的优先级和采样时机不相同。本篇介绍在使用RA-T系列芯片建立马达或电源工程时&#xff0c;如何根据需求来设置主要功能模块ADC&GPT&#xff0c;包括采样通道打包和分组&#xff0c;GPT触发启动…

Unity Shader学习6:多盏平行光+点光源 ( 逐像素 ) 前向渲染 (Built-In)

0 、分析 在前向渲染中&#xff0c;对于逐像素光源来说&#xff0c;①ForwardBase中只计算一个平行光&#xff0c;其他的光都是在FowardAdd中计算的&#xff0c;所以为了能够渲染出其他的光照&#xff0c;需要在第二个Pass中再来一遍光照计算。 而有所区别的操作是&#xff0…

tailwindcss学习01

系列教程 01 入门 02 vue中接入 入门 # 注意使用cmd不要powershell npm init -y # 如果没有npx则安装 npm install -g npx npm install -D tailwindcss3.4.17 --registry http://registry.npm.taobao.org npx tailwindcss init修改tailwind.config.js /** type {import(tai…

DIN:引入注意力机制的深度学习推荐系统,

实验和完整代码 完整代码实现和jupyter运行&#xff1a;https://github.com/Myolive-Lin/RecSys--deep-learning-recommendation-system/tree/main 引言 在电商与广告推荐场景中&#xff0c;用户兴趣的多样性和动态变化是核心挑战。传统推荐模型&#xff08;如Embedding &…

【前端】如何安装配置WebStorm软件?

文章目录 前言一、前端开发工具WebStorm和VS Code对比二、官网下载三、安装1、开始安装2、选择安装路径3、安装选项4、选择开始菜单文件夹5、安装成功 四、启动WebStorm五、登录授权六、开始使用 前言 WebStorm 是一款由 JetBrains 公司开发的专业集成开发环境&#xff08;IDE…

【Golang学习之旅】Go 语言微服务架构实践(gRPC、Kafka、Docker、K8s)

文章目录 1. 前言&#xff1a;为什么选择Go语言构建微服务架构1.1 微服务架构的兴趣与挑战1.2 为什么选择Go语言构建微服务架构 2. Go语言简介2.1 Go 语言的特点与应用2.2 Go 语言的生态系统 3. 微服务架构中的 gRPC 实践3.1 什么是 gRPC&#xff1f;3.2 gRPC 在 Go 语言中的实…

Spring核心思想之—AOP(面向切面编程)

目录 一 .AOP概述 二. Spring AOP 使用 2.1 引入AOP依赖 2.2 编写AOP程序 三. Spring AOP详情 3.1 切点(Pointcut) 3.2 连接点(Join Point&#xff09; 3.3通知&#xff08;Advice&#xff09; 3.4切面(Aspect) 3.5通知 3.6 PointCut &#xff08;公共切点&#xff09;…

关于使用雪花算法生成唯一ID,返回给前端ID不一致的问题

问题 在某个项目中,使用雪花算法生成的唯一ID,从数据库查询到数据后返回给前端,但是前端接受到的数据ID和数据库原先生成的不一致 但是前端展示的数据: 原因 原因是后端使用Long类型来存储雪花算法生成的ID,但是这个数值已经超过前端数值类型的范围,导致前端在存储这个数值…

axios post请求 接收sse[eventsource]数据的

axios 接收sse数据的 axios 接收sse数据的 EventSource什么 基于 HTTP 协议实现&#xff0c;通过与服务器建立一个持续连接&#xff0c;实现了服务器向客户端推送事件数据的功能。在客户端&#xff0c;EventSource 对象通过一个 URL 发起与服务器的连接。连接成功后&#xff0…

大语言模型常用微调与基于SFT微调DeepSeek R1指南

概述 大型语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;的微调&#xff08;Fine-tuning&#xff09;是指在一个预训练模型的基础上&#xff0c;使用特定领域或任务的数据对模型进行进一步训练&#xff0c;以使其在该领域或任务上表现更好。微调是迁移…

聚焦地灾防治,助力城市地质安全风险防控

城市是人类社会发展的重要载体&#xff0c;承载着经济繁荣、文化交流和人口聚集等重要功能。然而&#xff0c;由于城市建设过程中地质条件复杂&#xff0c;地质灾害风险隐患存在&#xff0c;城市地质安全等问题日益突出&#xff0c;引起人们的广泛关注。为保障城市发展的安全和…

为什么WP建站更适合于谷歌SEO优化?

在当今数字时代&#xff0c;建立一个网站似乎变得容易&#xff0c;但要构建一个真正能够带来流量和订单的网站却并非易事。特别是在谷歌SEO优化方面&#xff0c;不同的建站程序在SEO支持方面的效果差异显著。对于希望提升搜索引擎表现的用户来说&#xff0c;WordPress无疑是最佳…

用deepseek学大模型08-长短时记忆网络 (LSTM)

deepseek.com 从入门到精通长短时记忆网络(LSTM),着重介绍的目标函数&#xff0c;损失函数&#xff0c;梯度下降 标量和矩阵形式的数学推导&#xff0c;pytorch真实能跑的代码案例以及模型,数据&#xff0c; 模型应用场景和优缺点&#xff0c;及如何改进解决及改进方法数据推导…

(蓝桥杯——10. 小郑做志愿者)洛斯里克城志愿者问题详解

题目背景 小郑是一名大学生,她决定通过做志愿者来增加自己的综合分。她的任务是帮助游客解决交通困难的问题。洛斯里克城是一个六朝古都,拥有 N 个区域和古老的地铁系统。地铁线路覆盖了树形结构上的某些路径,游客会询问两个区域是否可以通过某条地铁线路直达,以及有多少条…

小胡说技书博客分类(部分目录):服务治理、数据治理与安全治理对比表格

文章目录 一、对比表格二、目录2.1 服务2.2 数据2.3 安全 一、对比表格 下表从多个维度对服务治理、数据治理和安全治理进行详细对比&#xff0c;为读者提供一个直观而全面的参考框架。 维度服务治理数据治理安全治理定义对软件开发全流程、应用交付及API和接口管理进行规范化…