38. 考古学家

news2025/1/6 6:19:57

题目描述

有一个考古学家发现一个石碑,但是很可惜,发现时其已经断成多段,原地发现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.coloradmin.cn/o/2270725.html

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

相关文章

浏览器选中文字样式

效果 学习 Chrome: 支持 ::selection。Firefox: 支持 :-moz-selection 和 ::selection。Safari: 支持 ::selection。Internet Explorer: 支持 :-ms-selection。Microsoft Edge: 支持 ::-ms-selection 和 ::selection。 代码 <!DOCTYPE html> <html lang"en&qu…

指代消解:自然语言处理中的核心任务与技术进展

目录 前言1. 指代消解的基本概念与分类1.1 回指与共指 2. 指代消解的技术方法2.1 端到端指代消解2.2 高阶推理模型2.3 基于BERT的模型 3. 事件共指消解&#xff1a;跨文档的挑战与进展3.1 联合模型3.2 语义嵌入模型&#xff08;EPASE&#xff09; 4. 应用场景与前景展望4.1 关键…

CDPHudi实战-集成spark

[一]使用Spark-shell 1-配置hudi Jar包 [rootcdp73-1 ~]# for i in $(seq 1 6); do scp /opt/software/hudi-1.0.0/packaging/hudi-spark-bundle/target/hudi-spark3.4-bundle_2.12-1.0.0.jar cdp73-$i:/opt/cloudera/parcels/CDH/lib/spark3/jars/; done hudi-spark3.4-bu…

leetcode:面试题 17.01. 不用加号的加法(python3解法)

难度&#xff1a;简单 设计一个函数把两个数字相加。不得使用 或者其他算术运算符。 示例: 输入: a 1, b 1 输出: 2 提示&#xff1a; a, b 均可能是负数或 0结果不会溢出 32 位整数 题解&#xff1a; class Solution:def add(self, a: int, b: int) -> int:sum_list [a…

设计模式 结构型 适配器模式(Adapter Pattern)与 常见技术框架应用 解析

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口&#xff0c;从而使原本因接口不兼容而无法一起工作的类能够协同工作。这种设计模式在软件开发中非常有用&#xff0c;尤其是在需要集成…

二维码文件在线管理系统-收费版

需求背景 如果大家想要在网上管理自己的文件&#xff0c;而且需要生成二维码&#xff0c;下面推荐【草料二维码】&#xff0c;这个系统很好。特别适合那些制造业&#xff0c;实体业的使用手册&#xff0c;你可以生成一个二维码&#xff0c;贴在设备上&#xff0c;然后这个二维码…

MySQL8安装与卸载

1.下载mysql MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压mysql安装包 解压到自己定义的目录&#xff0c;这里解压就是安装&#xff0c;解压后的路径不要有空格和中文。 3.配置环境变量 配置环境变量可以方便电脑在任何的路径…

数据挖掘——关联规则挖掘

数据挖掘——关联数据挖掘 关联数据挖掘关联规则关联规则挖掘问题&#xff1a;具体挖掘过程Apriori 产生关联规则 关联数据挖掘 关联分析用于发现隐藏在大型数据集中的令人感兴趣的联系&#xff0c;所发现的模式通常用关联规则或频繁项集的形式表示。 关联规则反映一个事物与…

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

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

Samsung手机首次主要采用竞对Micron LPDDR5内存

根据韩国媒体《韩国先驱报》&#xff08;The Korea Herald&#xff09;的报道&#xff0c;即将在1月底发布的三星 Galaxy S25 系列智能手机将首次主要使用美光科技&#xff08;Micron Technology&#xff09;提供的移动DRAM&#xff0c;而非三星自家的产品。这一消息对于三星的…

Linux驱动开发学习准备(Linux内核源码添加到工程-Workspace)

Linux内核源码添加到VsCode工程 下载Linux-4.9.88源码&#xff1a; 没有处理同名文件的压缩包&#xff1a; https://pan.baidu.com/s/1yjIBXmxG9pwP0aOhW8VAVQ?pwde9cv 已把同名文件中以大写命名的文件加上_2后缀的压缩包&#xff1a; https://pan.baidu.com/s/1RIRRUllYFn2…

leetcode题目(3)

目录 1.加一 2.二进制求和 3.x的平方根 4.爬楼梯 5.颜色分类 6.二叉树的中序遍历 1.加一 https://leetcode.cn/problems/plus-one/ class Solution { public:vector<int> plusOne(vector<int>& digits) {int n digits.size();for(int i n -1;i>0;-…

vue3+Echarts+ts实现甘特图

项目场景&#xff1a; vue3Echartsts实现甘特图;发布任务 代码实现 封装ganttEcharts.vue <template><!-- Echarts 甘特图 --><div ref"progressChart" class"w100 h100"></div> </template> <script lang"ts&qu…

接受Header使用错Map类型,导致获取到的Header值不全

问题复现 在 Spring 中解析 Header 时&#xff0c;我们在多数场合中是直接按需解析的。例如&#xff0c;我们想使用一个名为 myHeaderName 的 Header&#xff0c;我们会书写代码如下&#xff1a;RequestMapping(path "/hi", method RequestMethod.GET) public Str…

GitHub的简单操作

引言 今天开始就要开始做项目了&#xff0c;上午是要把git搭好。搭的过程中遇到好多好多的问题。下面就说一下git的简单操作流程。我们是使用的GitHub,下面也就以这个为例了 一、GitHub账号的登录注册 https://github.com/ 通过这个网址可以来到GitHub首页 点击中间绿色的S…

【时时三省】(C语言基础)常见的动态内存错误

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 对NULL指针的解引用操作 示例&#xff1a; malloc申请空间的时候它可能会失败 比如我申请一块非常大的空间 那么空间可能就会开辟失败 正常的话要写一个if&#xff08;p&#xff1d;&#x…

【51项目】51单片机自制小霸王游戏机

视频演示效果&#xff1a; 纳新作品——小霸王游戏机 目录&#xff1a; 目录 视频演示效果&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、连接方式&#xff1a; 1.1 控制引脚 1.2. 显示模块 1.3. 定时器 1.4. 游戏逻辑与硬件结合 1.5. 中断处理 二、源码分析&#xff1a…

ESP32-S3遇见OpenAI:OpenAI官方发布ESP32嵌入式实时RTC SDK

目录 OpenAI RTC SDK简介应用场景详解智能家居控制系统个人健康助手教育玩具 技术亮点解析低功耗设计快速响应高精度RTC安全性保障开发者指南 最近&#xff0c;OpenAI官方发布了一款针对ESP32-S3的嵌入式实时RTC&#xff08;实时时钟&#xff09;SDK&#xff0c;这标志着ESP32-…

Elasticsearch:减少 Elastic 容器镜像中的 CVE(常见的漏洞和暴露)

作者&#xff1a;来自 Elastic Maxime Greau 在这篇博文中&#xff0c;我们将讨论如何通过在 Elastic 产品中切换到最小基础镜像并优化可扩展漏洞管理程序的工作流程来显著减少 Elastic 容器镜像中的常见漏洞和暴露 (Common Vulnerabilities and Exposures - CVEs)。 基于 Chai…

计算机网络 (21)网络层的几个重要概念

前言 计算机网络中的网络层是OSI&#xff08;开放系统互连&#xff09;模型中的第三层&#xff0c;也是TCP/IP模型中的第二层&#xff0c;它位于数据链路层和传输层之间&#xff0c;负责数据包从源主机到目的主机的路径选择和数据转发。 一、网络层的主要功能 路由选择&#xf…