我必须通过递归检查一个数字是回文

时间:2017-03-08 09:51:47

标签: c

int main()
{
  int i,n;     
  printf("Enter the number");
  scanf("%d",&n);     
  i=pali(n);    
  if(n==i) 
    printf("Number is pall"); 
  else     
    printf("Not Pall");  
}  

int pali(int n) 
{   
  int r;  
  static sum=0;  
  if(n!=0) 
  {      
    r=n%10;    
    sum=sum*10+r;   
    pali(n/10);  
  }  
  return sum;
}

我使用静态变量来加总和。有没有办法不使用静态变量?

5 个答案:

答案 0 :(得分:2)

是的,典型的("功能")方法是以函数参数的形式传递状态。这通常使得有必要/很好的第二个函数执行实际的递归,你可以通过调用状态的正确初始值来开始:

int do_pali(int sum, int n)
{
  if(n != 0)
  {
    const int r = n % 10;
    return do_pali(10 * sum + r, n / 10);
  }
  return sum;
}

然后公共职能变成:

int pali(int n)
{
  return do_pali(0, n);
}

在具有内部功能的语言中,可以更清晰地表达(GCC支持将其作为扩展名)。

答案 1 :(得分:1)

当然,你可以这样做:

#include <stdio.h>

int pali(int n)
{
  int sum = 0;
  int keeper = 0;
  for (int i = n; i > 0; i /= 10) {
    if (keeper != 0) {
      sum *= 10;
      sum += (keeper - i * 10);
    }
    keeper = i;
  }
  sum *= 10;
  sum += keeper;
  return sum;
}

int main(int argc, char** argv)
{
  int i, n;     
  printf("Enter the number : ");
  scanf("%d",&n);
  i = pali(n);
  if(n == i) 
    printf("Number is palindrome"); 
  else     
    printf("Not Palindrome");  
}

使用递归更容易:

#include <stdio.h>

int pali(int n, int sum)
{
  sum += n - ((n / 10) * 10);
  n /= 10;
  if (n > 0)
    pali(n, sum * 10);
  else
    return sum;
}

int main(int argc, char** argv)
{
  int i, n;     
  printf("Enter the number : ");
  scanf("%d",&n);
  i = pali(n, 0);
  if(n == i) 
    printf("Number is palindrome"); 
  else     
    printf("Not Palindrome");  
}

只有一个参数的递归版本:

#include <stdio.h>

int pali(int n)
{
  int fUnit, lUnit;
  fUnit = n;
  int mul = 1;
  while (fUnit > 10) {
    fUnit /= 10;
    mul *= 10;
  }

  lUnit = n - ((n / 10) * 10);
  n -= (fUnit * mul);
  n /= 10;

  if (mul == 1) return 1;
  else if (fUnit == lUnit) return pali(n);
  else return 0;
}

int main(int argc, char** argv)
{
  int n;     
  printf("Enter the number : ");
  scanf("%d",&n);
  if(pali(n) == 1) 
    printf("Number is palindrome"); 
  else     
    printf("Not Palindrome");  
}

答案 2 :(得分:0)

由于您的函数返回sum,您可以替换此行:

pali(n/10);

sum=pali(n/10);

你也必须将它移动一条线。

答案 3 :(得分:0)

以下是

的优化版本
  • 不使用本地static
  • 仅包含stdio.h
  • 使用递归。
#include <stdio.h>

static void perform_useless_recursion (int n)
{
  if(n--)
  {
    perform_useless_recursion(n);
  }
}

_Bool is_pali (int n)
{
  perform_useless_recursion(1);

  int sum = 0;
  for(int i=n; i!=0; i/=10)
  {
    sum = sum*10 + i%10;
  }
  return n == sum;
}

int main (void)
{
  int n=5005;

  if(is_pali(n)) 
    printf("Number is pall"); 
  else     
    printf("Not Pall");  

  return 0;  
}

通过删除perform_useless_recursion()函数,可以进一步改进代码。

此代码的优点是实际计算由快速循环执行,而不是缓慢,危险的递归。在人工学校作业之外的现实世界中,当您编写高效且安全的代码时,没有理由编写低效且危险的代码。作为奖励,删除递归也会提供更易读的代码。

如果您对此代码进行基准测试,您会注意到它会比所有其他版本的内容更快并且消耗更少的内存。

答案 4 :(得分:0)

你可以创建一个只检查数字的第一个和最后一个数字的函数,然后传递剩下的数字。

为了更好地解释,请考虑以下情况:

  • pali( 1 22 0 )会检查第一个( 1 )和最后一个( 0 )数字。由于1!= 0 pali将返回false。

  • pali(1 789 1)将检查第一(1)和最后(1)。由于它们相等,所以函数会递归返回pali( 789 )(自7!= 9后它本身会返回false)。

  • pali( 878 )将检查8 = 8并递归返回pali( 7

  • pali( 3 )会检查第一个( 3 )和最后一个( 3 )数字是否相等并返回0。

这里的挑战是开发一种算法:

  • 检查第一个和最后一个数字是否相同(即使它只有一个数字!)

  • 从第一个和最后一个数字中删除数字,并在余数上调用

然后您需要做的就是应用递归。这是一个示例实现:

int pali(int number)
{
    int smallDigit, bigDigit;

    /* When recursion ends suceffuly*/
    if (number == 0)
        return 1;

    /* Check for first and last digit of a number */
    smallDigit = number % 10;
    bigDigit = number;

    while(bigDigit/10!=0)
    {
        bigDigit = bigDigit/10;
        smallDigit = smallDigit*10;
    }

    /* Check to see if both digits are equal (Note: you can't use smallDigit here because it's been multiplied by 10 a few times) */
    if (bigDigit != number%10)
        return 0;
    else
    {
        number = (number - smallDigit)/10; /* This is why smallDigit was multiplied by 10 a few times */
        return pali(number); /* Recursion time */
    }
}