完美的代价(c语言)PTA

本文介绍了如何通过最少的相邻字符交换次数将给定的非回文字符串转换为回文字符串,特别关注了奇数和偶数字符个数的情况处理。
摘要由CSDN通过智能技术生成

b7ada75ff38d4699a265f97085142fe8.png

解题思路:

        回文字符串有一个明显的特点即左右对称如:madam以‘d’为界限左右对称,很明显字符数为奇数且除了d外其他字母都成对存在,如果有两个d则为maddam,既然字符串呈轴对称那么就可以想到让对称轴左边不动,右边按照左边的顺序进行排列,排列时统计最少需要交换的次数。

注意!!题目中要求通过相邻两项的交换来时字符到达指定位置,因此不能跨越字符进行交换,跨越虽然也能使其达到效果,但记录出的次数不符合题目要求!!

现在来思考如何实现交换。可以从左边第一个字符开始如:mamda先用一个指针left指向他,再用一个指针right指向字符串最后一个元素。left先不动让right向左查找和left指向的字符相同的字符,如果找到了,就依次将其交换至最后一位,同时用count++记录交换的次数。之后让left指向下一个字符重复上述操作,显然这里使用双层for循环很方便外层代表left变化,里面一层代表right。由于没拍好一个字符所需要遍历的字符就少一个即right的起始位置就往前一个因此有需要tempz-1在每次排好一个后--来改变right起始位置。

如果遍历过程中发现该字符是单独的,即找到了单独的字符,就需要分情况:

1:字符串个数为奇数那么同时用一个变量来记录单独字符的个数,若大于一个则该字符串没法变成回文字符串,之后计算出该单独字符移到对称轴位置需要交换的次数加到count中即可。

2:字符串个数为偶数,只要出现单独的字符则一定无法构成回文字符串。

大概思路就是如此下面是具体代码。

#include<stdio.h>
void swap(char* p1, char* p2)//字符交换函数
{
    char temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
int fcounts(char* str, int sz)
{
    int count = 0,a=0;
    int left, right, tmp = sz - 1;
    for (left = 0; left <tmp; left++) //改变left指向的地方
    {
        for (right = tmp; right >= left; right--) //改变right指向的地方
        {
            if (left == right)  //如果left=right说明这个字符是单身因为不是单身的会走下面else中的代码
            {
                if (sz % 2 == 0)//如果是偶数个
                    return -1;
                else   //如果是奇数个
                {
                    a++;
                    count += sz / 2 - right;
                    break;
                }
            }

            else {
                if (str[left] == str[right])
                {
                    for (int z = right; z <tmp; z++)
                    {
                        swap(str + z, str + z + 1);
                        count++;
                    }
                    tmp--;//改变right起始位置
                    break;
                }
            }

        }if (a > 1)
              return -1;
    }
    return count;
}

int main()
{
    int n;
    scanf("%d", &n);
    getchar(); //scanf不会读取\n会导致下面的gets拿走\n所以要在这用getchar拿走\n导致其无法拿走本应拿走的字符串!!
    char str[81] = { 0 };
    gets(str);
    int result = fcounts(str, n);
    if (result == -1)
        printf("Impossible");
    else
        printf("%d", result);
    return 0;
}

 

        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值