求不超过n的最大回文数

我的想法很朴素,就是分奇偶情况讨论。

#include <stdio.h>
#include <string.h>
char s[509];
int len;
int compare()
{
    int mid = len / 2;
    int i, j;
    for (i = mid - 1, j = mid + 1; i >= 0; i--, j++)
    {
        if (s[i] > s[j])
        { // 前大于后
            return 0;
        }
        else if (s[i] < s[j])
        { // 后大于前
            return 1;
        }
    }
    return -1; //-1表明其本身即是回文数
}
int compare2()
{
    int mid = len / 2 - 1;
    int i, j;
    for (i = mid, j = mid + 1; i >= 0; i--, j++)
    {
        if (s[i] > s[j])
        { // 前大于后
            return 0;
        }
        else if (s[i] < s[j])
        { // 后大于前
            return 1;
        }
    }
    return -1; //-1表明其本身即是回文数
}
int search(int i)
{
    for (int tem = i; tem >= 0; tem--)
    {
        if (s[tem] != '0')
        {
            s[tem] = ((s[tem] - '0') - 1) + '0';
            return tem;
        }
        else
        {
            s[tem] = '9';
        }
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d", &T);
    for (int time = 0; time < T; time++)
    {
        scanf("%s", s);
        len = strlen(s);
        if (len & 1 == 1)
        { // 奇数
            int judge = compare();
            if (judge == -1)
            { // 其本身
                printf("%s\n", s);
                continue;
            }
            else if (judge == 1)
            { // 只修改奇数后半部分
                int k;
                for (k = 0; k <= len / 2; k++)
                {
                    printf("%c", s[k]);
                }
                for (k = len / 2 - 1; k >= 0; k--)
                {
                    printf("%c", s[k]);
                }
                printf("\n");
                continue;
            }
            else
            { // 需要向前查找第一个非0的数
                int pos = search(len / 2);
                if (s[pos] == '0' && pos == 0)
                {
                    for (int tem = 1; tem < len; tem++)
                    {
                        printf("9");
                    }
                    printf("\n");
                }
                else
                { // 输出
                    for (int tem = 0; tem <= len / 2; tem++)
                    {
                        printf("%c", s[tem]);
                    }
                    for (int tem = len / 2 - 1; tem >= 0; tem--)
                    {
                        printf("%c", s[tem]);
                    }
                    printf("\n");
                }
            }
        }
        else
        { // 偶数
            int judge = compare2();
            if (judge == -1)
            { // 其本身
                printf("%s\n", s);
                continue;
            }
            else if (judge == 1)
            {
                int k;
                for (k = 0; k <= len / 2 - 1; k++)
                {
                    printf("%c", s[k]);
                }
                for (k = len / 2 - 1; k >= 0; k--)
                {
                    printf("%c", s[k]);
                }
                printf("\n");
                continue;
            }
            else
            { // 需要向前查找第一个非0的数
                int pos = search(len / 2 - 1);
                if (s[pos] == '0' && pos == 0)
                {
                    for (int tem = 1; tem < len; tem++)
                    {
                        printf("9");
                    }
                    printf("\n");
                }
                else
                { // 输出
                    for (int tem = 0; tem <= len/2-1; tem++)
                    {
                        printf("%c", s[tem]);
                    }
                    for (int tem = len/2-1; tem >= 0; tem--)
                    {
                        printf("%c", s[tem]);
                    }
                    printf("\n");
                }
            }
        }
    }
    return 0;
}

之后,看到肖同学的方法很不错,在此记录一下。

根据回文数的性质,我们不难想到:
对于一个形如 ABCDEFGH 的整数
有且仅有一个比它大的最小回文数
有且仅有一个比它小的最大回文数
ABCDDCBA 一定是其中之一
例如:
36763是比36720大的最小回文数
90109是比90135小的最大回文数
所以对于本题,可以得出结论:
输入 ABCD ,若ABBA 比 ABCD 小,则 ABBA 就是比她小的最大回文数,然后就可
以直接输出这个答案了。
(即将原串的前一半,复制到后一半)

但是我们不能保证ABBA一定比ABCD

如果ABBAABCD大,那就要找比ABBA小的前一个回文数了

比如51412,按照上述操作得到51415,然而她大于了原来的数,就要找比她小的一个数,答案应该是51315

再举几个例子

输入398427,按照”ABBA”的想法得到398893,大了,重找,是397793

输入39023按照”ABBA”的想法得到39093,大了,重找,是38983

输入2000001,按照”ABBA”的想法得到2000002,大了,重找,是1999991

…………

可以看到,当“ABBA”大于原数的时候,我们为了找一个比原数小的数,要把中间位置减1,如果中间是0,就往前借位,同时0变成9

(为啥是中间位置呢?因为我们要保证这个数是最大数)

最后,需要注意一下特殊情况

比如1000的回文数,应该是999

按照“ABBA”的思想,得到1001,显然大了

但是这里再去减,会出现第一位是0的情况

因此类似10^k这种情况

我们特判一下就好

即这种情况下,答案就是k9

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值