C语言学习之 没有重复项数字的全排列

题目描述

给出一组数字,返回该组数字的所有排列

例如:

[1,2,3]的所有排列如下
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1].
(以数字在数组中的位置靠前为优先级,按字典序排列输出。)

数据范围:数字个数 0<n≤6

要求:空间复杂度 O(n!) ,时间复杂度 O(n!)

题目分析

        题目中是给定一个数组,该数组是没有重复项的,纯数字的。要求输出的是其内部元素排列组合后形成的多个数组。

        根据题意可知,需输出的是一个二维数组,行数为数组元素个数的排列组合数,我们需要一个内存空间存放这么多数组。题目中源数组长度最大为6个,即最多有6*5*4*3*2*1 =720个数组结果。考虑到实际问题可能需要更多,我们采用申请动态空间的方式开辟这些数组所需的内存。

        根据题意,输出的是一个个的数组,所以需要每个数组对应的行数、列数。

        根据题意,输出结果要“以数字在数组中的位置靠前为优先级,按字典序排列输出”。

        这一题对我来说相对困难,经过多次尝试后,最终选择使用递归的思路求解。

        递归思路中,需要将问题逐步分解,使所有操作都能由一个简单程序完成。题目中排列组合,在之前的课中有类似练习,当时是通过交换两个元素的思路完成的,这里想到递归之后,第一时间我就想到用交换的思路。

        以题目中 1 2 3 数组为例,将1 分别与2、3交换,就能得到1 2 3 ;2 1 3;3 1 2。再对1 2 3 ; 2 1 3 ; 3 1 2中的后两位分别进行交换,就能得到1 3 2 ;2 3 1;3 2 1。同理,其他长度的数组也可以使用这种思路排列。

        题目中又要求顺序,所以需要考虑交换后的数组顺序是否为题目要求的,如不满足,还需进行调整。

        基于以上思路,进行如下编码。

代码如下:

#include <stdio.h>	//NULL标识需要引用 stdio.h 文件
#include <malloc.h>	//申请动态内存需要引用 malloc.h 文件

void swap(int* a, int* b)	//将地址a和地址b中的数值交换
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

//设置一个索引 index,用于调换源数组不同位的元素,以及返回调用前位置
void re_permute(int* num, int index, int numLen, int* returnSize, int** returnColumnSizes, int** res)
{
	int i = 0;
	if (index == numLen)	//索引到最后一位时,将num数组赋值给当前行数组
	{
		res[*returnSize] = (int*)malloc(numLen * sizeof(int));	//申请动态内存,存放一行数组
		for (i = 0; i < numLen; i++)	//数组循环赋值
		{
			res[*returnSize][i] = num[i];
		}
		(*returnColumnSizes)[*returnSize] = numLen;	
		//对应行数组列数,即数组长度,为numLen
		(*returnSize)++;	//每次赋值后,行数+1
	}

	for (i = index; i < numLen; i++)	//从索引
	{
		swap(&num[i], &num[index]);		//每一位轮流与索引位交换
		//数组较长时,需两次交换满足题目要求,执行以下判断
		if ((numLen - index) > 2 && index != i)	
		{
			swap(&num[i], &num[index + 1]);	//保证交换顺序符合题目要求
			re_permute(num, index + 1, numLen, returnSize, returnColumnSizes, res);
			//索引位+1,到末位时,整个数组排序结束,再+1,进入数组赋值环节
			swap(&num[i], &num[index + 1]);	//后交换的先复原
		}
		else
		{
			re_permute(num, index + 1, numLen, returnSize, returnColumnSizes, res);
			//索引位+1,到末位时,整个数组排序结束,再+1,进入数组赋值环节
		}
		swap(&num[i], &num[index]);	//每一位轮流与索引位交换,即还原
	} 

}

// @param num int整型一维数组
// @param numLen int num数组长度
// @return int整型二维数组
// @return int* returnSize 返回数组行数
// @return int** returnColumnSizes 返回数组列数

int** permute(int* num, int numLen, int* returnSize, int** returnColumnSizes) 
{
	// write code here
	if (numLen == 0)
		return NULL;
	int i = 0;
	int count = 1;
	for(i = 1; i <= numLen; i++)	//计算所需的行数
		count *= i;
	*returnColumnSizes = (int*)malloc(count * sizeof(int));	
	//每一行对应一个列数,将列数以数组形式记录,方便后续调用
	//申请动态内存,存储列数数组
	int** res = (int**)malloc(count * sizeof(int*));	
	//申请动态内存,存放结果数组
	*returnSize = 0;			//数组列数,从0开始计算						
	re_permute(num,0,numLen, returnSize,returnColumnSizes, res);	
	//将res数组地址作为参数,方便改动其中内容
	
	return res;	//前面是地址传参,这里可以直接返回数组首元素地址。
}

        代码中,将交换函数、排列函数分别作为子函数,方便调试和理解。在主函数中,先判断数组中有无数字;再为数组行数、列数申请动态内存。

        交换函数没有什么特别的,就是地址指向的元素的交换。

        排列函数中,先对递归的尽头进行定义,防止出现死递归。递归的尽头就是数组所有元素都排列完,这时就可以将该排列输出。然后是递归的主体,本着按顺序排列组合的思路,依次对数组首位(index = 0),第二位(index=1),第三位,第四位...进行交换。考虑题目要求顺序,又对交换后顺序进行调整,最后进行输出。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openpnp - 视觉原点的位置要离设备的软限制点远一点

文章目录 openpnp - 视觉原点的位置要离设备的软限制点远一点笔记备注END openpnp - 视觉原点的位置要离设备的软限制点远一点 笔记 最开始的视觉原点&#xff0c;是在设备X 0, Y 0的附近位置&#xff0c;粘了一块20x20x20的铝块&#xff0c;铝块上面贴着用黑塑料皮打印的1…

esp8266 at指令链接wifi时一直connect disconnest

那是你的连接wifi的名字密码有误或者热点有问题&#xff0c;看看热点是不是把设备拉入黑名单或者设置为5G或者连了校园网或者设置了最多链接设备

IntelliJ IDEA 2024.2 新特性概览

文章目录 1、重点特性:1.1 改进的 Spring Data JPA 支持1.2 改进的 cron 表达式支持1.3 使用 GraalJS 作为 HTTP 客户端的执行引擎1.4 更快的编码时间1.5 K2 模式下的 Kotlin 性能和稳定性改进 2、用户体验2.1 改进的全行代码补全2.2 新 UI 成为所有用户的默认界面2.3 Search E…

C++模拟实现vector容器【万字模拟✨】

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; 学习专栏C语言_Stark、的博客-CSDN博客 项目实战C系列_Stark、的博客-CSDN博客 数据结构与算法_Stark、的博客-CSDN博客 座右铭&#xff1a;梦想是一盏明灯&#xff…

设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、原型模式2、原型模式的使用场景3、优点4、缺点5、主要角色6、代码示例7、总结题外话关于使用序列化实现深拷贝 设计模式概述 创建型模式&#xff1a;工厂方法、抽象方法、建造者、原型、单例。 结构型模式有&#xff1a;适配器、桥接、组合、装饰器、…

深度学习中的结构化概率模型 - 结构化概率模型的深度学习方法篇

序言 在深度学习的广阔领域中&#xff0c;结构化概率模型&#xff08; Structured Probabilistic Model \text{Structured Probabilistic Model} Structured Probabilistic Model&#xff09;扮演着至关重要的角色。这类模型利用图论中的图结构来表示概率分布中随机变量之间的…

Spring Boot ⽇志

目录 1.⽇志使⽤ 2.⽇志级别 3.⽇志配置 3.1配置⽇志级别 3.2⽇志持久化 3.3配置⽇志⽂件分割 4.更简单的⽇志输出 1.⽇志使⽤ 在使用之前我们先来了解一下为什么要使用&#xff1f; ⽇志的⽤途 1.系统监控 我们可以通过⽇志记录这个系统的运⾏状态&#xff0c;对数…

20款奔驰CLS300升级原厂抬头显示HUD 23P智能辅助驾驶 触摸屏人机交互系统

以下是为您生成的一份关于 18 款奔驰 CLS 老款改新款的改装文案&#xff1a; 18 款奔驰 CLS 老款改新款&#xff1a;科技升级&#xff0c;畅享极致驾驶体验 在汽车改装的世界里&#xff0c;每一次的升级都是对卓越的追求。今天&#xff0c;让我们一同探索 18 款奔驰 CLS 老款改…

在登陆功能中添加Redis缓存

目录 基于Redis实现短信登录 实现流程图 实现代码 解决登录状态刷新问题 初始方案思路&#xff1a; 实现代码 发送验证码 登陆实现 如果是新用户则自动创建 运行测试 基于Redis实现短信登录 实现流程图 实现代码 Overridepublic Result login(LoginFormDTO loginForm…

Thinkphp/Laravel旅游景区预约系统的设计与实现

目录 技术栈和环境说明具体实现截图设计思路关键技术课题的重点和难点&#xff1a;框架介绍数据访问方式PHP核心代码部分展示代码目录结构解析系统测试详细视频演示源码获取 技术栈和环境说明 采用PHP语言开发&#xff0c;开发环境为phpstudy 开发工具notepad并使用MYSQL数据库…

【深度学习】— 多层感知机介绍、 隐藏层、从线性到非线性、线性模型的局限性

【深度学习】— 多层感知机介绍 4.1 多层感知机4.1.1 隐藏层线性模型的局限性引入隐藏层 4.2 从线性到非线性线性组合的局限性引入非线性堆叠更多隐藏层 4.1 多层感知机 在第 3 节中&#xff0c;我们介绍了 softmax 回归&#xff0c;并实现了其从零开始的实现和基于高级 API 的…

如何在dblp官网下载外文文献

文章目录 零、dblp官网一、直接下载pdf二、Zotero 零、dblp官网 ①老域名&#xff1a;https://dblp.uni-trier.de/ ②简化域名&#xff1a;dblp.org 一、直接下载pdf 1.举例&#xff0c;搜索 image matching 2.直接点击红色的PDF按钮 (可能会因为卡&#xff0c;点了没反应。…

No.3 笔记 | Web安全基础:Web1.0 - 3.0 发展史

大家好&#xff01;作为一个喜欢探索本质的INTP&#xff0c;我整理了一份简明易懂的Web安全笔记。希望能帮助你轻松掌握这个领域的核心知识。 这份笔记涵盖了Web发展的历程&#xff0c;从静态的Web 1.0到智能化的Web 3.0。我们将探讨URL和HTTP协议&#xff0c;揭示它们在网络中…

24-10-2-读书笔记(二十二)-《契诃夫文集》(一)上([俄] 契诃夫 [译] 汝龙)啊!真想生活。

文章目录 《契诃夫文集》&#xff08;一&#xff09;上&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09;早期生活——塔甘罗格&#xff08;人物家庭简介&#xff09;学生时期——莫斯科&#xff08;写作与学习&#xff09;流浪时期——哈萨林&#xff08;游历与流浪&#xff09…

Java中的封装、继承、多态

目录 封装 概念 包 继承 多态 向上转型 一、直接赋值 二、方法传参 三、返回值 向上转型注意事项 向下转型 格式 重写 重写和重载的区别 动态绑定 静态绑定和动态绑定 封装 概念 简单来说就是套壳屏蔽细节。 举例&#xff1a; 想要访问它们时需要一些“接口”…

Java项目实战II基于Java+Spring Boot+MySQL的大创管理系统(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者 一、前言 在当前创新创业氛围浓厚的背景下&#xff0c;大学生创新创业项目&#xff08;简称“大创”&#xff0…

国内旅游:现状与未来趋势分析

在当今社会快速发展的背景下&#xff0c;国内旅游更是呈现出蓬勃的发展态势。中国&#xff0c;这片拥有悠久历史、灿烂文化和壮丽山河的广袤土地&#xff0c;为国内旅游的兴起与发展提供了得天独厚的条件。 本报告将借助 DataEase 强大的数据可视化分析能力&#xff0c;深入剖…

基于SpringBoot的学习资源共享平台

运行环境: jdk8tomcat9mysqlIntelliJ IDEAmavennodejs 设计选用前后端分离的单体架构方式 后端&#xff1a;SpringBootMybatis-PluslogbackElasticsearchRedisMySQLJwtsmtp阿里云OSS 前端&#xff1a;WebPackVueJsAnt Designaxios 主要模块&#xff1a;反馈管理、资源管理、…

【最新】微信小程序连接onenet——stm32+esp8266+onenet实现查看温湿度,控制单片机

微信小程序——stm32esp8266onenet实现查看温湿度&#xff0c;控制单片机 &#xff08;最新已验证&#xff09;stm32 新版 onenet dht11esp8266/01s mqtt物联网上报温湿度和控制单片机(保姆级教程) &#xff1a;↓↓&#x1f447; &#x1f447; &#x1f447; &#x1f447…

unreal engine5制作动作类游戏时,我们使用刀剑等武器攻击怪物或敌方单位时,发现攻击特效、伤害等没有触发

UE5系列文章目录 文章目录 UE5系列文章目录前言一、问题分析二、解决方法1. 添加项目设置碰撞检测通道2.玩家角色碰撞设置3.怪物角色碰撞预设 最终效果 前言 在使用unreal engine5制作动作类游戏时&#xff0c;我们使用刀剑等武器攻击怪物或敌方单位时&#xff0c;发现攻击特效…