38. 考古学家

题目描述

有一个考古学家发现一个石碑,但是很可惜,发现时其已经断成多段,原地发现n个断口整齐的石碑碎片。为了破解石碑内容,考古学家希望有程序能帮忙计算复原后的石碑文字组合数,你能帮忙吗?

输入描述

第一行输入n,n表示石碑碎片的个数。

第二行依次输入石碑碎片上的文字内容s,共有n组。

输出描述

输出石碑文字的组合(按照升序排列),行末无多余空格。

用例

输入3
a b c
输出abc
acb
bac
bca
cab
cba
说明
输入3
a b a
输出aab
aba
baa
说明
一、问题分析

首先读题,仔细看描述中的内容,发现需求是

1.有一个考古学家发现一个石碑,但是很可惜,发现时其已经断成多段

2.原地发现n个断口整齐的石碑碎片

3.为了破解石碑内容,考古学家希望有程序能帮忙计算复原后的石碑文字组合数

4.输入描述:第一行输入n,n表示石碑碎片的个数。

第二行依次输入石碑碎片上的文字内容s,共有n组。

5.输出描述:输出石碑文字的组合(按照升序排列),行末无多余空格。

二、解题思路

1.首先我们读取碎片个数int n;

scanf("%d", &n);

2.然后我们读取文字内容,存储为一个二维字符数组(通过动态分配内存实现)

char **fragments = (char **)malloc(n * sizeof(char *));

for(int i = 0; i < n; i++) {

fragments[i] = (char *)malloc(100 * sizeof(char));

scanf("%s", fragments[i]);

}

3.然后通过递归的方式手动生成所有可能的碎片文字排列组合情况,将这些排列组合存储在另一个动态分配内存的二维字符数组中。

char **result = NULL;

int resultSize = 0;

permute(fragments, 0, n, &result, &resultSize);

4.之后对这些排列组合进行排序

qsort(result, resultSize, sizeof(char *), compare);

5.排序后去除重复的组合

removeDuplicates(&result, &resultSize);

6.之后逐行输出这些排列组合

for(int i = 0; i < resultSize; i++) {

printf("%s\n", result[i]);

free(result[i]);

}

7.释放动态分配的内存避免内存泄漏

free(fragments);

free(result);

return 0;

8.使用到的库有标准库,标准输入输出库,字符串处理库

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

9.定义一个交换函数,用于交换两个字符指针所指向的字符串,在生成排列组合的过程中,通过交换指针指向的字符串来改变顺序,从而得到不同的排列情况。它接受两个二级字符指针作为参数,通过中间临时指针temp实现两个指针所指向字符串的交换。

void swap(char **a, char **b) {

char *temp = *a;

*a = *b;

*b = temp;

}

10.生成排列组合函数,这是一个递归函数,用于生成给定字符串数组fragments的所有全排列情况,并将结果存储到动态分配内存的result数组中,同时通过resultSize指针记录结果数组的大小(元素个数)。

递归终止条件:当start参数等于size - 1时,表示已经固定了前面所有位置的元素,当前位置就是最后一个位置了,此时已经生成了一种完整的排列组合。首先为这个新的排列组合分配足够的内存空间(根据每个碎片字符串长度和碎片个数计算所需字节数,额外加1是为了存储字符串结束符\0),然后通过循环将各个碎片字符串拼接起来形成一个完整的排列组合字符串newPerm。接着使用realloc函数动态调整result数组的内存大小,为新的排列组合字符串分配空间,并将其存储到result数组中,同时更新resultSize值。

递归生成排列组合部分:在start小于size - 1时,通过循环将当前位置start的元素与它后面的元素依次交换(通过调用swap函数),然后对剩余的元素(即从start + 1位置开始)递归调用permute函数来生成所有可能的排列情况,在一次递归调用返回后,再将交换的元素交换回来,回复原来的顺序,继续下一次交换和递归调用,以此类推,最终生成所有的排列组合情况。

void permute(char **fragments, int start, int size, char ***result, int *resultSize) {

if(start == size - 1) {

char *newPerm = (char *)malloc((strlen(fragments[0]) * size + 1) * sizeof(char));

newPerm[0] = '\0';

for(int i = 0; i < size; i++) {

strcat(newPerm, fragments[i]);

}

(*result) = (char **)realloc(*result, (*resultSize + 1) * sizeof(char **));

(*result)[*resultSize] = newPerm;

(*resultSize)++;

return;

}

for(int i = start; i < size; i++) {

swar(&fragments[start], &fragments[i]);

permute(fragments, start + 1, size, result, resultSize);

swap(&fragments[start], &fragments[i]);

}

}

11.比较函数,为qsort排序函数提供自定义的比较规则。qsort函数要求传入一个比较函数指针,用于比较两个元素的大小关系。在这里,比较的元素是字符指针(指向字符串),所以先通过*(char **)a和*(char **)b解引用得到实际的字符指针,再使用strcmp函数比较这两个指针所指向的字符串的大小(按照字典序比较),返回比较结果,供qsort函数根据这个结果对数组元素进行排序。

int compare(const void *a, const void *b) {

return strcmp(*(char **)a, *(char **)b);

}

12.去重函数,用于去除result数组中的重复字符串。通过循环遍历result数组,比较相邻的两个字符串(使用strcmp函数),如果不相等,就将当前字符串保留(将其复制到索引为j的位置,同时j自增1);如果相等,说明是重复的字符串,就释放其占用的内存空间(通过free函数)。最后将最后一个字符串也添加到去重后的数组中,并更新resultSize的值为去重后的数组元素个数,实现去重功能。

void removeDuplicates(char ***result, int *resultSize) {

int i, j;

for(int i = 0, j = 0; i < *resultSize - 1; i++) {

if(strcmp((*result)[i], (*result)[i + 1]) != 0) {

(*result)[j++] = (*result)[i];

}else {

free((*result)[i]);

}

}

(*result)[j++] = (*result)[*resultSize - 1];

*resultSize = j;

}

三、具体步骤

使用的语言是C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 交换两个字符串
void swap(char **a, char **b) {char *temp = *a;*a = *b;*b = temp;
}// 生成全排列的函数,采用递归的方式
void permute(char **fragments, int start, int size, char ***result, int *resultSize) {if (start == size - 1) {// 为新的排列组合分配内存空间char *newPerm = (char *)malloc((strlen(fragments[0]) * size + 1) * sizeof(char));newPerm[0] = '\0';for (int i = 0; i < size; i++) {strcat(newPerm, fragments[i]);}// 将新的排列组合添加到结果数组中(*result) = (char **)realloc(*result, (*resultSize + 1) * sizeof(char **));(*result)[*resultSize] = newPerm;(*resultSize)++;return;}for (int i = start; i < size; i++) {swap(&fragments[start], &fragments[i]);permute(fragments, start + 1, size, result, resultSize);swap(&fragments[start], &fragments[i]);}
}// 比较两个字符串指针指向的字符串是否相等
int compare(const void *a, const void *b) {return strcmp(*(char **)a, *(char **)b);
}// 去除结果数组中的重复字符串
void removeDuplicates(char ***result, int *resultSize) {int i, j;for (i = 0, j = 0; i < *resultSize - 1; i++) {if (strcmp((*result)[i], (*result)[i + 1])!= 0) {(*result)[j++] = (*result)[i];} else {free((*result)[i]);}}(*result)[j++] = (*result)[*resultSize - 1];*resultSize = j;
}int main() {int n;scanf("%d", &n);char **fragments = (char **)malloc(n * sizeof(char *));for (int i = 0; i < n; i++) {fragments[i] = (char *)malloc(100 * sizeof(char));  // 假设每个碎片字符串最长100个字符,可根据实际调整scanf("%s", fragments[i]);}char **result = NULL;int resultSize = 0;permute(fragments, 0, n, &result, &resultSize);// 排序qsort(result, resultSize, sizeof(char *), compare);// 去重removeDuplicates(&result, &resultSize);for (int i = 0; i < resultSize; i++) {printf("%s\n", result[i]);free(result[i]);}free(fragments);free(result);return 0;
}

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

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

相关文章

17爬虫:关于DrissionPage相关内容的学习01

概述 前面我们已经大致了解了selenium的用法&#xff0c;DerssionPage同selenium一样&#xff0c;也是一个基于Python的网页自动化工具。 DrissionPage既可以实现网页的自动化操作&#xff0c;也能够实现收发数据包&#xff0c;也可以把两者的功能合二为一。 DressionPage的…

计算机网络•自顶向下方法:网络层介绍、路由器的组成

网络层介绍 网络层服务&#xff1a;网络层为传输层提供主机到主机的通信服务 每一台主机和路由器都运行网络层协议 发送终端&#xff1a;将传输层报文段封装到网络层分组中&#xff0c;发送给边缘路由器路由器&#xff1a;将分组从输入链路转发到输出链路接收终端&#xff1…

下载linux aarch64版本的htop

htop代码网站似乎没有编译好的各平台的包&#xff0c;而自己编译需要下载一些工具&#xff0c;比较麻烦。这里找到了快速下载和使用的方法&#xff0c;记录一下。 先在linux电脑上执行&#xff1a; mkdir htop_exe cd htop_exe apt download htop:arm64 # 会直接下载到当前目…

呼叫中心中间件实现IVR进入排队,判断排队超时播放提示音

文章目录 [TOC](文章目录) 前言需求排队结束原因 联系我们实现步骤1. 调用http接口返回动作2. 启用拨号方案 前言 需求 呼叫中心需要实现调用IVR接口进入排队&#xff0c;如果是因为等待超时导致退出排队的&#xff0c;那就播放一段提示音再挂断通话&#xff1b;其他的情况就…

如何二次封装组件(vue3版本)

在开发 Vue 项目中我们一般使用第三方组件库进行开发&#xff0c;如 Element-Plus, 但是这些组件库提供的组件并不一定满足我们的需求&#xff0c;这时我们可以通过对组件库的组件进行二次封装&#xff0c;来满足我们特殊的需求。 对于封装组件有一个大原则就是我们应该尽量保…

【74HC192减法24/20/72进制】2022-5-17

缘由用74ls192设计一个72进制的减法计数器&#xff0c;需要有逻辑电路图-硬件开发-CSDN问答

Fastapi项目通过Jenkins2.4.91自动化构建部署到Nginx1.20进行访问详细方法(完全自动化部署亲测可用)

这篇技术文章需要结合我写的前两篇文章来一起看Gitlab17.7Jenkins2.4.91实现Fastapi/Django项目持续发布版本详细操作(亲测可用) 和 Pycharm2024.3Gitlab.17.7本地化部署和自动提交代码使用方法&#xff08;亲测可用&#xff09;&#xff0c;总体来说是三部曲。这篇文章详细解读…

iOS 11 中的 HEIF 图像格式 - 您需要了解的内容

HEIF&#xff0c;也称为高效图像格式&#xff0c;是iOS 11 之后发布的新图像格式&#xff0c;以能够在不压缩图像质量的情况下以较小尺寸保存照片而闻名。换句话说&#xff0c;HEIF 图像格式可以具有相同或更好的照片质量&#xff0c;同时比 JPEG、PNG、GIF、TIFF 占用更少的设…

DATACOM-DHCP-复习-实验

DHCP 概述工作原理DHCP分配机制 配置配置基于全局地址池的DHCP服务器配置DHCP Relay中继验证 实验配置DHCP中继 参考 概述 动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;用于集中对用户IP地址进行动态管理和…

深入浅出 Beam Search:自然语言处理中的高效搜索利器

Beam Search 技术详解 搜索系列相关文章&#xff08;置顶&#xff09; 1.原始信息再加工&#xff1a;一文读懂倒排索引 2.慧眼识词&#xff1a;解析TF-IDF工作原理 3.超越TF-IDF&#xff1a;信息检索之BM25 4.深入浅出 Beam Search&#xff1a;自然语言处理中的高效搜索利器 1…

二、CSS基础

一、选择器(1) 大白话&#xff1a;我们人为认为的解析方式是&#xff0c;从左往右查找&#xff0c;对于浏览器来说&#xff0c;是从右往左查找&#xff0c;解析速度更高。 注&#xff1a; 伪类选择器 - 作用于实际存在的元素&#xff0c;用于描述元素的某种特定状态或关系&…

从摩托罗拉手机打印短信的简单方法

昨天我试图从摩托罗拉智能手机上打印短信&#xff0c;但当我通过USB将手机连接到电脑时&#xff0c;我在电脑上找不到它们。由于我的手机内存已达到限制&#xff0c;并且我想保留短信的纸质版本&#xff0c;您能帮我将短信从摩托罗拉手机导出到计算机吗&#xff1f; 如您所知&…

Linux终端输入删除键backspace显示^H,输入上下左右键显示^A^B^C^D原理以及详细解决办法!

当我们装完Linux系统之后,我们可能会碰到按下删除键后出现^H这种情况。 同样,输入上下左右键显示^A^B^C^D这种情况。 这是为什么呢? 别急,后面我会说具体解决办法,先来看看这是为什么? 一、终端程序架构 首先,我们需要了解终端程序架构。 终端程序架构分为三层,分别…

ESP32 I2S音频总线学习笔记(一):初识I2S通信与配置基础

文章目录 简介为什么需要I2S&#xff1f;关于音频信号采样率分辨率音频声道 怎样使用I2S传输音频&#xff1f;位时钟BCLK字时钟WS串行数据SD I2S传输模型I2S通信格式I2S格式左对齐格式右对齐格式 i2s基本配置i2s 底层API加载I2S驱动设置I2S使用的引脚I2S读取数据I2S发送数据卸载…

JAVA:利用 Redis 实现每周热评的技术指南

1、简述 在现代应用中&#xff0c;尤其是社交媒体和内容平台&#xff0c;展示热门评论是常见的功能。我们可以通过 Redis 的高性能和丰富的数据结构&#xff0c;轻松实现每周热评功能。本文将详细介绍如何利用 Redis 实现每周热评&#xff0c;并列出完整的实现代码。 2、需求分…

vscode代码AI插件Continue 安装与使用

“Continue” 是一款强大的插件&#xff0c;它主要用于在开发过程中提供智能的代码延续功能。例如&#xff0c;当你在编写代码并且需要进行下一步操作或者完成一个代码块时&#xff0c;它能够根据代码的上下文、语法规则以及相关的库和框架知识&#xff0c;为你提供可能的代码续…

kafka开机自启失败问题处理

前言&#xff1a;在当今大数据处理领域&#xff0c;Kafka 作为一款高性能、分布式的消息队列系统&#xff0c;发挥着举足轻重的作用。无论是海量数据的实时传输&#xff0c;还是复杂系统间的解耦通信&#xff0c;Kafka 都能轻松应对。然而&#xff0c;在实际部署和运维 Kafka 的…

Linux Red Hat 7.9 Server安装GitLab

1、关闭防火墙 执行 systemctl disable firewalld 查看服务器状态 systemctl status firewalld 2、禁用selinux vi /etc/selinux/config 将SELINUX 的值改为 disabled 3、安装policycoreutils-python 执行 yum install policycoreutils-python 4、下载gitlab wget --co…

PostgreSQL对称between比较运算

本文介绍PostgreSQL对称between比较功能&#xff1a;between symmetric&#xff0c;在动态拼接SQL时利用它可以简化判断。PostgreSQL 9.4 及以上版本支持BETWEEN SYMMETRIC操作符&#xff0c;MySQL、Oracle、MsSQL没有对应功能。 between 比较 PostgreSQL的between结构允许你对…

[CTF/网络安全] 攻防世界 simple_php 解题详析

题目描述&#xff1a;小宁听说php是最好的语言,于是她简单学习之后写了几行php代码。 代码解读 $a$_GET[a]; 从HTTP GET请求参数中获取一个名为a的变量&#xff0c;并将其赋值给变量a。符号用于禁止错误输出&#xff0c;如果不存在参数a则会将变量a设置为NULL。 $b$_GET[b];…