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 hereif (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.mzph.cn/web/54688.shtml

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

相关文章

【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现

项目搭建 创建项目 # 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js} 使用npx create-react-app创建项目&#xff0…

网站优化门槛低了还是高了?

自从2015年刚接触网站时&#xff0c;从一无所知到现在无人指导&#xff0c;一直跌跌撞撞走过来&#xff0c;当年花了1500元找了广东一个网友用织梦CMS做了一个门户网站&#xff0c;记得那时一星期没下楼&#xff0c;把网站折腾的千疮百孔&#xff0c;而终逐步熟悉网站建设与搜索…

【在Linux世界中追寻伟大的One Piece】DNS与ICMP

目录 1 -> DNS(Domain Name System) 1.1 -> DNS背景 2 -> 域名简介 2.1 -> 域名解析过程 3 -> 使用dig工具分析DNS 4 -> ICMP协议 4.1 -> ICMP功能 4.2 -> ICMP报文格式 4.3 -> Ping命令 4.4 -> traceroute命令 1 -> DNS(Domain Na…

webGL进阶(一)多重纹理效果

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&q…

Matter蓝牙解析

解析 Matter 蓝牙广播 定义需要解析的字段。 #import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN/// 蓝牙广播服务 ID extern NSString * const MatterBLEAdvServiceID;@interface MatterBLEAdv : NSObject @property (nonatomic, assign) NSInteger opCode; @…

【Unity踩坑】Unity导出的UWP项目编译失败

在Unity中导出了UWP平台的项目后&#xff08;Xaml或D3D&#xff09;&#xff0c;使用Visual Studio编译时发生错误&#xff1a; Error: Unity.IL2CPP.Building.BuilderFailedException: Lump_libil2cpp_vm.cpp 查找后发现是Visual Studio 与Unity兼容的问题 原贴&#xff1a;…

黑神话:仙童,数据库自动反射魔法棒

黑神话&#xff1a;仙童&#xff0c;数据库自动反射魔法棒 Golang 通用代码生成器仙童发布了最新版本电音仙女尝鲜版十一及其介绍视频&#xff0c;视频请见&#xff1a;https://www.bilibili.com/video/BV1ET4wecEBk/ 此视频介绍了使用最新版的仙童代码生成器&#xff0c;将 …

使用YOLOv11进行视频目标检测

使用YOLOv11进行视频目标检测 完整代码 import cv2 from ultralytics import YOLOdef predict(chosen_model, img, classes[], conf0.5):if classes:results chosen_model.predict(img, classesclasses, confconf)else:results chosen_model.predict(img, confconf)return r…

view deign 和 vue2 合并单元格的方法

1.vue版本和view design 版本 {"vue": "^2.6.11","view-design": "^4.7.0", }2.Data中定义数据 spanArr: [], // 某一列下需要合并的行数 pos: 0// 索引// 注意点&#xff1a; 在获取列表前&#xff0c;需要重置 this.spanArr [] 注…

C++-容器适配器- stack、queue、priority_queue和仿函数

目录 1.什么是适配器 2.deque 1.简单了解结构 2.deque的缺陷 3.为什么选择deque作为stack和queue的底层默认容器 3.stack&#xff08;栈&#xff09; 4.queue&#xff08;队列&#xff09; 5.仿函数 6.priority_queue&#xff08;优先级队列&#xff09;&#xff08;堆…

切片辅助超推理-sahi库-get_sliced_prediction源码简析

代码地址&#xff1a;https://github.com/obss/sahi get_sliced_prediction源码中重要是理解nms或nmm。nms经常遇到不说。 其中nmm即Non-Max Merging算法是最重要部分&#xff0c;它其实和nms比较类似。其具体原理我看到了一片博客&#xff0c;感觉讲的很好&#xff0c;如下&a…

Linux C接口编程入门之文件I/O

一切皆文件 "Linux一切皆文件"是Linux操作系统中的一个重要理念和设计原则。在Linux系统中&#xff0c;几乎所有的设备、资源都以文件的形式进行访问和操作。简化了操作系统的设计和管理&#xff0c;提供了一种统一的抽象模型&#xff0c;使得应用程序可以使用相同的…

docker简述

1.安装dockers&#xff0c;配置docker软件仓库 安装&#xff0c;可能需要开代理&#xff0c;这里我提前使用了下好的包安装 启动docker systemctl enable --now docker查看是否安装成功 2.简单命令 拉取镜像&#xff0c;也可以提前下载使用以下命令上传 docker load -i imag…

【gRPC】1—gRPC是什么

gRPC是什么 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; &#x1f4d6;RPC专栏&#xff1a;https://b…

数据工程师岗位常见面试问题-3(附回答)

数据工程师已成为科技行业最重要的角色之一&#xff0c;是组织构建数据基础设施的骨干。随着企业越来越依赖数据驱动的决策&#xff0c;对成熟数据工程师的需求会不断上升。如果您正在准备数据工程师面试&#xff0c;那么应该掌握常见的数据工程师面试问题&#xff1a;包括工作…

脉冲下跳沿提取电路

本例中的电路可将负脉冲转换为正脉冲。尽管这个任务看似简单&#xff0c;但负脉冲的幅度为-5V~-2V。按照不同应用要求&#xff0c;正脉冲也需要不同的脉冲宽度&#xff0c;而负脉冲是梯形的。脉冲必须先经过一个长距离的传输线才能到达某个控制设备。有多个电路可以解决这一问题…

jQuery——解决快速点击翻页的bug

本文分享到此结束&#xff0c;欢迎大家评论区相互讨论学习&#xff0c;下一篇继续分享jQuery中内置动画的学习。

谷歌AI大模型Gemini API快速入门及LangChain调用视频教程

1. 谷歌Gemini API KEY获取及AI Studio使用 要使用谷歌Gemini API&#xff0c;首先需要获取API密钥。以下是获取API密钥的步骤&#xff1a; 访问Google AI Studio&#xff1a; 打开浏览器&#xff0c;访问Google AI Studio。使用Google账号登录&#xff0c;若没有账号&#xf…

大数据ETL数据提取转换和加载处理

什么是 ETL&#xff1f; 提取转换加载&#xff08;英语&#xff1a;Extract, transform, load&#xff0c;简称ETL&#xff09;&#xff0c;用来描述将资料从来源端经过抽取、转置、加载至目的端的过程。ETL一词较常用在数据仓库&#xff0c;但其对象并不限于数据仓库。 ETL&…

C++竞赛初阶—— 石头剪子布

题目内容 石头剪子布&#xff0c;是一种猜拳游戏。起源于中国&#xff0c;然后传到日本、朝鲜等地&#xff0c;随着亚欧贸易的不断发展它传到了欧洲&#xff0c;到了近现代逐渐风靡世界。简单明了的规则&#xff0c;使得石头剪子布没有任何规则漏洞可钻&#xff0c;单次玩法比…