简体   繁体   English

c-查找回文

[英]c - find palindrome

I'm a newcomer to programming, and I chose C as my first language(been learning it for a month or so). 我是编程的新手,我选择C作为第一语言(学习了一个月左右)。 I've been trying to solve this palindrome question for hours and still couldn't come up with a satisfying solution. 我已经尝试解决这个回文问题几个小时了,但仍然无法提出令人满意的解决方案。 The question is here (from SPOJ), and here's my code: 问题在这里 (来自SPOJ),这是我的代码:

#include <stdio.h>
#include <string.h>
void plus_one(char *number);
int main(void)
{
    char number[1000001];
    int i, j, m, k, indicator;
    int a;
    scanf("%d", &j);
    for (i = 0; i < j; i++) {
        scanf("%s", number);
        k = 1;
        while (k != 0) {
            plus_one(number);
            a = strlen(number);
            indicator = 1;
            for (m = 0; m < a / 2; m++) {
                if (number[m] != number[a - m - 1]) {
                    indicator = 0;
                    break;
                }
            }
            if (indicator != 0) {
                printf("%s\n", number);
                k = 0;
            }
        }
    }
    return 0;
}

void plus_one(char *number)
{
    int a = strlen(number);
    int i;
    number[a - 1]++;
    for (i = a; i >= 0; i--){
        if (number[i - 1] == ':') {
            number[i - 1] = '0';
            number[i - 2]++;
        }
        else
            break;
    }
    if (number[0] == '0') {
        number[0] = '1';
        strcat(number, "0");
    }
    return;
}

My idea was to examine every number greater than the input until a palindrome is found, and it worked well on my computer. 我的想法是检查每个大于输入的数字,直到找到回文,并且在我的计算机上运行良好。 But SPOJ responded "time limit exceeded", so I guess I need to find the next palindrome possible myself instead of using brute force. 但是SPOJ回答“超过了时间限制”,所以我想我需要自己寻找下一个回文,而不要使用蛮力。 Can someone please give me a hint about how I can make this go faster? 有人可以给我提示我如何使它更快吗? Thanks! 谢谢!

Since you're asking for a hint and not for C code (which I'm notoriously bad at), here's what I would do: 由于您是在寻求提示,而不是C代码(这是我所不擅长的),因此,我将执行以下操作:

  1. Determine if the number k has an even or odd number of digits, store that in a boolean called odd . 确定数字k是否具有偶数或奇数个数字,然后将其存储在称为odd的布尔值中。
  2. Take the first half of the number k , including the middle digit if odd is true, and store it in a variable called half . 取数字k的前半部分,如果odd为true,则包括中间数字,并将其存储在名为half的变量中。
    808 -> 80 808 > 80
    2133 -> 21 2133 > 21
  3. Mirror the half variable, taking care to not duplicate the middle digit if odd is true, and store it in a variable called mirror . 镜像half变量,注意如果odd为true,则不要重复中间数字,并将其存储在名为mirror的变量中。
    80 -> 808 80 > 808
    21 -> 2112 21 > 2112
  4. Check if mirror > k 检查mirror > k
    • If true: you found your result 如果为真:您找到了结果
    • If false: increment half and start over from step 3. 如果为假,则增加half ,然后从步骤3重新开始。
      (After maximum one increment you're guaranteed to have found your result.) (最大增量后,您可以保证找到您的结果。)
      80 -> 81 -> 818 80 > 81 > 818
      21 -> 22 -> 2222 21 > 22 > 2222

Here's a JavaScript implementation for your reference: 这是一个JavaScript实现,供您参考:

 const palin = (k) => { const mirror = (half, odd) => half + Array.from(half).reverse().join('').substring(odd); const s = k.toString(); const odd = s.length % 2; const half = s.substring(0, Math.floor(s.length / 2) + odd); let mirrored = mirror(half, odd); if (+mirrored <= k) { mirrored = mirror((+half + 1).toString(), odd); } return mirrored; } console.log(palin(5)); console.log(palin(808)); console.log(palin(2133)); 

Welcome to the site. 欢迎来到该网站。 What you have posted is commendable for someone who has only been using C for a month! 您发布的内容对于只使用C一个月的人来说是值得称赞的! Anyway ... I think your suspicion is correct. 无论如何...我认为您的怀疑是正确的。 Using 'brute force' to find the next palindrome is probably the not to way go. 用“蛮力”寻找下一个回文可能是不可行的。

This question is as much about algorithm design as about C. Nonetheless, how you handle char[] representations of integers in C is interesting and relevant. 这个问题和关于C的算法设计一样多。尽管如此,如何在C中处理整数的char[]表示很有趣且相关。 FWIW, my attempt is pasted below. FWIW,我的尝试粘贴在下面。

It accepts a char[] representation of the number ( n ) and the number of digits ( k ) as arguments, and returns 1 on success or 0 on failure (another pass needed). 它接受数字( n )和数字位数( k )的char[]表示作为参数,并在成功时返回1或在失败时返回0 (需要另一回合)。

static int next_palindrome(char *n, size_t k) {
    unsigned i = 0, carry = 0;
    char tmp = 0;
    int finished = 1;

    for (i = 0; i < k; i++) {
        if (carry) {
            finished = 0;
            *(n + k - i - 1) = *(n + k - i - 1) + 1;
            if (*(n + k - i - 1) == 10) {
                *(n + k - i - 1) = 0;
                carry = 1;
            } else
                carry = 0;
            continue;
        }
        if (i >= k / 2) continue;
        if (*(n + k - i - 1) == *(n + i)) continue;
        tmp = *(n + k - i - 1);
        *(n + k - i - 1) = *(n + i);
        if (tmp > *(n + i)) {
            carry = 1;
        }
    }

    return finished;
}

I have only tested it on numbers with < 64 digits so far, but have no reason to believe it will fail for larger numbers of digits. 到目前为止,我仅对<64位数字进行了测试,但是没有理由相信更大的数字会失败。

Sample usage: http://codepad.org/3yyI9wEl 用法示例: http//codepad.org/3yyI9wEl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM