LTC659 2024-11-03 12:00 采纳率: 57.1%
浏览 27
已结题

有关“完美的代价”问题的代码漏洞

题目
完美的代价
描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)

输入描述:
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出描述:
如果可能,输出最少的交换次数。
否则输出Impossible

输入样例:
5
mamad
输出样例:
3

下面是本人所写代码,大致思路是通过交换先解决字符串两边,再解决中间:

#include <stdio.h> 
//以下先声明一个交换函数,每次交换相邻数组,交换次数(stp)+1 
void swpt(char* a,char* b,int* stp)
{
    char* temp;
    temp = a;
    a = b;
    b = temp;
    *stp++;
}

int main()
{
    int len;//声明数组长度 
    scanf("%d",&len);//从键盘读取数组长度 
    char a[len];//声明字符串数组 
    scanf("%s",&a);//从键盘读取字符串数组 
    int k=len-1,stp=0,non_match=0;//初始化未解决范围k,交换次数stp ,不存在匹配的字母数 non_match
    for(int i=0;i<=k;i++)//从左开始遍历需要配对的 a【i】 
    {
        for(int j=k;j>=i;j--)// 从右开始遍历寻找与a【i】 配对的 a【j】  
        {
            if(a[i]==a[j]&&i!=j)//如果找到 
            {
                    for(int x=j;x<=k-1;x++)//将a【j】移动至未解决范围内最左端 
                    {
                        swpt(a+x,a+x+1,&stp);        
                    }
                
                k--;//缩小未解决范围 
            }
            else if(a[i]==a[j]&&i==j)//如果未找到,a【i】则为不存在匹配的字母
            {
                if(i<=(len-1)/2)//a【i】偏左,移动至中间 
                {
                    for(int x=i;x<=(len-1)/2-1;x++)
                        {
                            swpt(a+x,a+x+1,&stp);        
                        }
                    non_match++;
                }
                else// a【i】偏右,移动至中间 
                {
                    for(int x=i;x>=(len-1)/2+1;x--)
                        {
                            swpt(a+x,a+x-1,&stp);        
                        }
                    non_match++;
                }
            } 
        }
    }
    //讨论输出结果 
    if(non_match>1) printf("Impossible");//如果不存在匹配的字母数大于1,无论奇偶,都不可能是回文串 
    else if(non_match==1)// 如果存在一个不存在匹配的字母
    {
        if(len%2==0) printf("Impossible");//如果长度为偶数,不可能是回文串  
        else printf("%d",stp);//如果长度为奇数,输出交换次数 
    }
    else //如果没有不存在匹配的字母
    {
        if(len%2==1) printf("Impossible");//如果长度为奇数,不可能是回文串 
        else printf("%d",stp);//如果长度为偶数,输出交换次数 
    }
    
    return 0;
}

输入测试:
5
mamad
输出测试:
Impossible

显然代码存在错误
请依据本人的代码寻找错误并修改或改进,请不要重写代码,谢谢!

  • 写回答

29条回答 默认 最新

  • 专家-皆知 2024-11-03 12:01
    关注
    获得0.15元问题酬金

    以下回复引自免费微信小程序:皆我百晓生。 如问题解决,还请采纳。如仍有疑问,请回复留言或私信博主,以便获得更精准的帮助。

    在你的代码中,有几个明显的错误和改进点:

    1. 交换函数的实现错误:在 swpt 函数中,直接交换指针不会改变数组中的字符位置。应该交换指针指向的字符,而不是指针本身。

    2. 数组长度声明和输入:在声明字符数组时,不应该使用变量长度(C语言标准不允许)。可以使用动态内存分配或者固定大小的数组。

    3. 交换次数的增加:在 swpt 函数中,*stp++ 应该是 (*stp)++

    4. 字符串处理逻辑:处理字符串时,应该确保每次交换后更新字符数组的内容。

    5. 输出逻辑错误:判断字符串是否能成为回文串的条件有误。

    下面是修改后的代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // 声明一个交换函数,每次交换相邻数组,交换次数(stp)+1
    void swpt(char* a, char* b, int* stp) {
        char temp = *a;
        *a = *b;
        *b = temp;
        (*stp)++;
    }
    
    int main() {
        int len; // 声明数组长度
        scanf("%d", &len); // 从键盘读取数组长度
        char a[8001]; // 声明字符数组,最大长度为8000
        scanf("%s", a); // 从键盘读取字符串数组
    
        int k = len - 1, stp = 0, non_match = 0; // 初始化未解决范围k,交换次数stp,不存在匹配的字母数 non_match
    
        for (int i = 0; i <= k; i++) { // 从左开始遍历需要配对的 a[i]
            for (int j = k; j >= i; j--) { // 从右开始遍历寻找与a[i] 配对的 a[j]
                if (a[i] == a[j] && i != j) { // 如果找到
                    for (int x = j; x < k; x++) { // 将a[j]移动至未解决范围内最左端
                        swpt(&a[x], &a[x + 1], &stp);
                    }
                    k--; // 缩小未解决范围
                    break;
                } else if (j == i) { // 如果未找到,a[i]则为不存在匹配的字母
                    if (len % 2 == 0 || non_match > 0) {
                        printf("Impossible\n");
                        return 0;
                    }
                    non_match++;
                    for (int x = i; x < len / 2; x++) { // 将a[i]移动至中间
                        swpt(&a[x], &a[x + 1], &stp);
                    }
                }
            }
        }
    
        // 输出结果
        printf("%d\n", stp);
    
        return 0;
    }
    

    主要修改点:

    1. 交换函数:修改了 swpt 函数,直接交换字符而不是指针。
    2. 数组声明:使用固定大小的数组 char a[8001] 来存储输入字符串。
    3. 字符串处理逻辑:在找到配对的字符时,将其移到正确的位置,并更新 k 的值。
    4. 输出逻辑:根据 non_match 的值来判断是否可能形成回文串,并在适当的时候输出 Impossible

    测试用例:

    输入:
    5
    mamad
    输出:
    3
    

    经过这些修改,代码应该能够正确地处理输入并输出正确的结果。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 11月11日
  • 创建了问题 11月3日

悬赏问题

  • ¥15 r语言Hurst指数
  • ¥15 Acrn IVSHMEM doorbell问题
  • ¥15 yolov5中的val测试集训练时数量变小问题
  • ¥15 MPLS/VPN实验中MPLS的配置问题
  • ¥15 materialstudio氢键计算问题
  • ¥15 echarts图表制作
  • ¥15 halcon根据玻璃面板纹路取区域
  • ¥15 HFSS设计小型化180度耦合器
  • ¥15 使用CInternetSession,CHttpFile读取网页文件时有些电脑上会卡住怎么办?
  • ¥15 水下机器人的半物理仿真研究