力扣第47题“全排列 II”

题目描述

给定一个可能包含重复元素的整数数组 nums,返回所有不重复的排列。

示例:

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

解题思路

  1. 排序去重:先对数组 nums 进行排序,方便在递归生成排列时去重。
  2. 回溯法生成排列:类似全排列问题(46题),使用回溯法,但在选择元素时,跳过重复的元素以避免重复排列。
  3. 使用标记数组:使用一个布尔数组 used 来标记元素是否被选择过。对于相邻的重复元素,若前一个相同元素未被使用,则跳过当前元素,以保证生成的排列不重复。

代码实现

以下是详细的代码实现及逐行注释:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>typedef struct {int** data;       // 存储所有排列结果int* columnSizes; // 每个排列的长度int size;         // 当前排列的数量int capacity;     // 容量
} ResultArray;// 初始化结果数组
ResultArray* createResultArray(int capacity) {ResultArray* result = (ResultArray*)malloc(sizeof(ResultArray));result->data = (int**)malloc(capacity * sizeof(int*));result->columnSizes = (int*)malloc(capacity * sizeof(int));result->size = 0;result->capacity = capacity;return result;
}// 添加排列到结果数组
void addResult(ResultArray* result, int* permutation, int length) {if (result->size >= result->capacity) {result->capacity *= 2;result->data = (int**)realloc(result->data, result->capacity * sizeof(int*));result->columnSizes = (int*)realloc(result->columnSizes, result->capacity * sizeof(int));}result->data[result->size] = (int*)malloc(length * sizeof(int));for (int i = 0; i < length; i++) {result->data[result->size][i] = permutation[i];}result->columnSizes[result->size] = length;result->size++;
}// 比较函数,用于排序
int cmp(const void* a, const void* b) {return *(int*)a - *(int*)b;
}// 递归函数生成排列
void backtrack(int* nums, int numsSize, int* permutation, int level, bool* used, ResultArray* result) {if (level == numsSize) {  // 生成完整排列addResult(result, permutation, numsSize);return;}for (int i = 0; i < numsSize; i++) {// 跳过重复元素if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;if (!used[i]) {  // 选择一个未使用的数字used[i] = true;permutation[level] = nums[i];backtrack(nums, numsSize, permutation, level + 1, used, result);  // 递归used[i] = false;  // 回溯}}
}// 主函数
int** permuteUnique(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {ResultArray* result = createResultArray(100);  // 初始化结果数组int* permutation = (int*)malloc(numsSize * sizeof(int));bool* used = (bool*)calloc(numsSize, sizeof(bool));// 排序数组,便于去重处理qsort(nums, numsSize, sizeof(int), cmp);backtrack(nums, numsSize, permutation, 0, used, result);*returnSize = result->size;*returnColumnSizes = result->columnSizes;free(permutation);free(used);return result->data;
}// 测试代码
int main() {int nums[] = {1, 1, 2};int numsSize = sizeof(nums) / sizeof(nums[0]);int returnSize;int* returnColumnSizes;int** result = permuteUnique(nums, numsSize, &returnSize, &returnColumnSizes);printf("所有不重复排列结果:\n");for (int i = 0; i < returnSize; i++) {printf("[");for (int j = 0; j < returnColumnSizes[i]; j++) {printf("%d", result[i][j]);if (j < returnColumnSizes[i] - 1) printf(", ");}printf("]\n");free(result[i]);}free(result);free(returnColumnSizes);return 0;
}

代码解析

  1. 排序数组

    qsort(nums, numsSize, sizeof(int), cmp);
    

    排序数组,使得相同的数字相邻,便于去重。

  2. 跳过重复元素

    if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
    
    • 当遇到重复元素时,只有在前一个相同元素已被使用的情况下才允许当前元素被选中。
    • 这确保了排列过程中不包含重复项。
  3. 递归生成排列

    void backtrack(int* nums, int numsSize, int* permutation, int level, bool* used, ResultArray* result)
    
    • 使用 used 数组标记数字是否已被使用。
    • 每次递归生成完整排列时,调用 addResult 保存排列结果。
  4. 主函数 permuteUnique

    • 初始化结果数组 ResultArray,调用 backtrack 函数生成所有不重复排列。
    • 设置 returnSizereturnColumnSizes 用于返回结果。

复杂度分析

  • 时间复杂度O(n * n!),其中 n 为数组长度。生成的排列数量为 n!,每个排列的生成需要 O(n) 的时间。
  • 空间复杂度O(n * n!),存储所有不重复排列结果的空间复杂度。

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

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

相关文章

408最后冲刺阶段,怎么做题才能考到120+?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 重要性排序如下&#xff1a;真题占据首位&#xff0c;紧随其后的是王道模拟题&#xff0c;王道书与题目则紧随其后&#xff0c;而408统考配套习题&#xff08;高教版&#xff09;与之大致相当。 真题&#xff0c;无疑…

如何对接低价又稳定的影视会员渠道?

对接低价折扣影视会员渠道通常涉及到与影视内容提供商或第三方分销商的合作。以下是一些基本步骤和注意事项&#xff0c;帮助你顺利对接这类渠道&#xff1a; 1. 市场调研 了解市场&#xff1a;研究市场上现有的影视会员服务提供商&#xff0c;包括价格、服务、用户反馈等。确…

crond 任务调度 (Linux相关指令:crontab)

相关视频链接 crontab 进行 定时任务 的设置 概述 任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序 任务调度的分类&#xff1a; 1.系统工作&#xff1a;有些重要的工作必须周而复始地执行。如病毒扫描等。 2.个别用户可能希望执行某些程序&#xff0c;比如…

顺序表+ArrayList

文章目录 一、基础知识1.1 数据结构类的继承图1.2 List 介绍1.3 线性表 二、数据结构 -- 顺序表2.1 什么是顺序表以及优缺点2.2 用数组实现顺序表细节解析代码 三、ArrayList3.1 Java中如何使用ArrayList3.2 ArrayList源码无参构造方法add方法扩容方法指定初始容量构造利用其他…

【工具变量】排污权交易政策试点DID(2000-2023)

数据简介&#xff1a;在过去几十年间的“高增长、高能耗、高污染”的经济发展背景下&#xff0c;随着社会各界不断反应高经济增长背后付出的巨大环境代价&#xff0c;中国ZF将节能环保减排纳入长期规划治理中。在2007年&#xff0c;我国开始启动了二氧化硫&#xff08;SO2&…

通用特效Shader

一、通用特效Shader介绍 1.1 什么是通用特效材质 Unity支持SRP Batcher后&#xff0c;使用UberShader的优势非常明显。所谓&#xff0c;UberShader&#xff0c;即一个超级Shader&#xff0c;覆盖一类功能&#xff0c;而不是多个分散的小Shader&#xff0c;比如一个通用特效Sh…

网络安全SQL初步注入2

六.报错注入 mysql函数 updatexml(1,xpath语法,0) xpath语法常用concat拼接 例如: concat(07e,(查询语句),07e) select table_name from information_schema.tables limit 0,1 七.宽字节注入(如果后台数据库的编码为GBK) url编码:为了防止提交的数据和url中的一些有特殊意…

Golang--面向对象

Golang语言面向对象编程说明&#xff1a; Golang也支持面向对象编程(OOP)&#xff0c;但是和传统的面向对象编程有区别&#xff0c;并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。Golang没有类(class)&#xff0c;Go语言的结构体(struct)和其…

英国留学论文写作中复合句式基础知识讲解

从句子的结构出发&#xff0c;复合句式是将两个以上的独立、完整的字句子通过coordinating conjunction或者分号连接在一起。因此&#xff0c;复合句式可以理解成为两个以上的简单句子组合在一起。下面英国翰思教育通过举例的方式&#xff0c;来介绍如何将独立的句子连接在一起…

从奇富科技,QQ钱包看信贷服务、贷款超市的的客户注册认证流程有什么不同

概览 奇富科技作为港股信贷第一企业&#xff0c;目前已服务2.4亿用户&#xff0c;是国内头部信贷科技服务平台。 QQ钱包&#xff0c;作为8亿用户的贷款超市&#xff0c;拥有其他贷款超市产品梦寐以求的流量入口。 产品模式 奇富科技作为信贷科技服务平台&#xff0c;主要提…

寻找伤感短视频素材 这些网站帮你轻松下载无水印资源

无论是制作情感类短视频&#xff0c;还是为抖音视频寻找合适的素材&#xff0c;伤感视频素材一直是创作者们关注的重点。如果你正在为如何找到高质量的伤感素材而困扰&#xff0c;那么今天我将推荐一些非常实用的素材网站&#xff0c;帮助你快速找到适合的伤感视频素材&#xf…

Java项目实战II基于Spring Boot的大学生智能消费记账系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在当今社会…

Linux 抓包工具 --- tcpdump

序言 在传输层 Tcp 的学习中&#xff0c;我们了解了 三次握手和四次挥手 的概念&#xff0c;但是看了这么多篇文章&#xff0c;我们也只是停留在 纸上谈兵。  欲知事情如何&#xff0c;我们其实可以尝试去看一下具体的网络包的信息。在这篇文章中将向大家介绍&#xff0c;在 L…

基于Spring Boot+Vue的养老院管理系统【原创】

一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a; 技术&#xff1a;框架Vue.js&#xff1b;UI库&#xff1a;ElementUI&#xff1b; 开发工具&…

基于SpringBoot+Vue音乐播放和推荐系统【提供源码+答辩PPT+参考文档+项目部署】

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

震撼!通过双重异步,Excel 10万行数据导入从191秒优化到2秒!

震撼&#xff01;通过双重异步&#xff0c;Excel 10万行数据导入从191秒优化到2秒&#xff01; 在现代的企业级应用开发中&#xff0c;海量数据的处理效率和并发性能优化是一个非常重要的课题。无论是大规模数据导入、文件解析&#xff0c;还是在分布式系统中处理高并发任务&a…

Linux编程:用于调试 C、C++ 和其他编程语言编写的程序的调试工具GDB的使用

目录 一、概述 二、 安装GDB 三、准备程序 四、使用GDB 1、启动GDB 2、获取帮助 五、 常用GDB命令 六、示例调试会话 七、其他事项 一、概述 GDB&#xff08;GNU Debugger&#xff09;是一个非常强大的调试工具&#xff0c;广泛用于调试 C、C 和其他编程语言编写的程序…

书生实战营第四期-基础岛第五关-XTuner 微调个人小助手认知

基础任务 使用 XTuner 微调 InternLM2-Chat-7B 实现自己的小助手认知 一、环境配置与数据准备 1.构建虚拟环境 cd ~ #git clone 本repo git clone https://github.com/InternLM/Tutorial.git -b camp4 mkdir -p /root/finetune && cd /root/finetune conda create -…

java day04-面向对象基础(内存 封装 继承 修饰符 工具类 )

1.对象内存图 1.1 Java 内存分配 1.2 堆和栈 栈:所有局部变量都会在栈内存中创建 局部变量&#xff1a;定义在方法中的变量或者方法声明上的变量 方法执行都会加载到栈中进行 -----------------------------------------------------------------------------------------…

【C++练习】二进制到十进制的转换器

题目&#xff1a;二进制到十进制的转换器 描述 编写一个程序&#xff0c;将用户输入的8位二进制数转换成对应的十进制数并输出。如果用户输入的二进制数不是8位&#xff0c;则程序应提示用户输入无效&#xff0c;并终止运行。 要求 程序应首先提示用户输入一个8位二进制数。…