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

题目描述

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

例如:

1,2,3\]的所有排列如下 \[1,2,3\],\[1,3,2\],\[2,1,3\],\[2,3,1\],\[3,1,2\], \[3,2,1\]. (以数字在数组中的位置靠前为优先级,按字典序排列输出。) 数据范围:数字个数 0\ //NULL标识需要引用 stdio.h 文件 #include //申请动态内存需要引用 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),第三位,第四位...进行交换。考虑题目要求顺序,又对交换后顺序进行调整,最后进行输出。

相关推荐
jelasin3 分钟前
LibCoroutine开发手记:细粒度C语言协程库
c语言
篝火悟者12 分钟前
自学-C语言-基础-数组、函数、指针、结构体和共同体、文件
c语言·开发语言
genispan33 分钟前
QT/C++ 多线程并发下载实践
开发语言·c++·qt
-代号95271 小时前
【JavaScript】十三、事件监听与事件类型
开发语言·javascript·ecmascript
写代码的小王吧1 小时前
【Java可执行命令】(十)JAR文件签名工具 jarsigner:通过数字签名及验证保证代码信任与安全,深入解析 Java的 jarsigner命令~
java·开发语言·网络·安全·web安全·网络安全·jar
小卡皮巴拉1 小时前
【力扣刷题实战】矩阵区域和
开发语言·c++·算法·leetcode·前缀和·矩阵
努力搬砖的咸鱼2 小时前
Qt中的数据解析--XML与JSON处理全攻略
xml·开发语言·qt·json
Pacify_The_North2 小时前
【C++进阶三】vector深度剖析(迭代器失效和深浅拷贝)
开发语言·c++·windows·visualstudio
Song2 小时前
JVM 学习计划表(2025 版)
jvm·学习
神里流~霜灭2 小时前
蓝桥备赛指南(12)· 省赛(构造or枚举)
c语言·数据结构·c++·算法·枚举·蓝桥·构造