【问题标题】:C reverse a number recursivlyC递归地反转一个数字
【发布时间】:2018-01-12 13:00:14
【问题描述】:

我有一个任务来创建一个接收数字并返回反转数字的函数。

E.G:

Input : 12343 
Output : 34321

不允许循环,输入只有数字。

这是我尝试过的:

long GetReverse(unsigned long n)
{
    if (n < 10)
        return n % 10;
    else
        return  10 * GetReverse(n / 10) + n % 10;
}

虽然这是重新调整我相同的输入而不是反转数字(我知道这里有什么问题,我只是想不出办法)

有什么想法吗?

编辑:这是我想出的解决方案:

int numOfMulti(unsigned long num) {
    if (num < 10)
        return 1;
    return 10 * numOfMulti(num / 10); 
}

long GetReverse(unsigned long n)
{
    if (n < 10)
        return n % 10; 
    else
        return  n % 10 * numOfMulti(n) + GetReverse(n / 10) ; 
}

在没有辅助函数或静态变量的情况下无法找到解决方案。

【问题讨论】:

  • 澄清一下,你不需要帮助来理解为什么会发生这种情况,只是为了帮助你想出一个合适的算法来得到正确的解决方案?
  • @Someprogrammerdude 没错..
  • 铅笔。纸。尝试 10 到 100 之间的数字。调整算法。现在尝试一个介于 100 和 1000 之间的数字。适应.. 冲洗,重复。
  • ...并考虑另一种数据结构。例如一串数字。
  • @sagi 你可以拥有多个功能吗?在这种情况下,让您的函数调用另一个带有两个参数的函数。

标签: c algorithm recursion


【解决方案1】:

这很容易。请尝试我的解决方案。没有循环,只有一个参数。

long GetReverse(unsigned long n)
{
    static unsigned long m = 0;
    static int recursive_level = 0;
    recursive_level++;
    if (n < 10) {
        recursive_level--;
        m = m * 10 + n;
        int temp = m;
        if (recursive_level == 0) {
            m = 0;
        }
        return temp;
    }
    m = m * 10 + (n % 10);
    GetReverse(n / 10);
    recursive_level--;
    int temp = m;
    if (recursive_level == 0) {
        m = 0;
    }
    return temp;   
 }

【讨论】:

  • 如果该函数被第二次调用会发生什么?
  • @VladfromMoscow,谢谢,让我们多想想。
  • 我不确定它是否特别简单,但它确实可以完成这项工作,并且在线程安全方面并不比rand() 差。 +1。
  • @VladfromMoscow,我修改了我的答案。
  • 谢谢,我不知道我是否可以使用静态变量,但我会投票,因为它提供了一个很好的答案
【解决方案2】:

您需要将 2 个元素传递给 GetReverse 函数,因为最后一位数字必须向左移动:

long GetReverse(unsigned long n, unsigned long m)
{
    if (n < 10)
        return 10 * m + n;
    else
        return  GetReverse(n / 10, 10 * m + n % 10);
}

然后您可以拨打GetReverse(12343, 0) 并获得预期的34321

【讨论】:

  • 我知道如何使用附加元素来做到这一点。但正如我所说,我只需要使用一个参数
  • 您可以通过创建带有 1 个参数的 GetReverse 函数和带有 2 个参数的 _GetReverse 函数来绕过 2 参数问题。让GetReverse调用递归的_GetReverse函数。
  • +1,这是唯一真正明智的答案。在 C++ 中,您可以为 m 使用默认参数,这样会更好。
【解决方案3】:

这很傻,不应该在现实生活中使用,但符合要求:

unsigned long GetReverse(unsigned long n)
{
    if (n < 10)
        return n;
    else
        return n % 10 * lround(pow(10,floor(log10(n)))) + GetReverse(n / 10);
}

【讨论】:

  • 很遗憾并不总是有效:见stackoverflow.com/questions/21452711/…
  • @Bathsheba 它应该始终有效,因为我是 lrounding 而不是截断。
  • @sagi,不需要浮点代码来解决整数问题。
  • 进一步这仍然存在@Bathsheba指出的问题,因为它使用了floor(log10(n))。如果log10(n) 返回 x.9999999 而不是 x+1,结果是错误的。 lround() 不保存。
  • @chux 为了我的辩护,我可以说至少对于10^n 没有风险,因为结果将乘以010^n+1 有可能获得无效值,但我不确定是否存在实际发生这种情况的系统。
【解决方案4】:

这是一个只需要一个参数的解决方案,尽管您只能使用最低有效 32 位作为输入:

uint64_t rev(uint64_t n)
{
    uint32_t _n = n;
    uint32_t _m = n >> 32;
    return _n < 10 
        ? 10 * _m + _n
        : rev(_n / 10 + (uint64_t)(10 * _m + _n % 10) * 65536 * 65536)
    ;
}

int main(){
    uint32_t n = 12345;
    n = rev(n);
}

本质上,系数存储在n 的高阶位中。在许多方面,这是一个可怕的发明,因为我所做的只是使用一个应该有两个参数的参数,并且我依赖于调用站点上的(定义明确的)缩小无符号转换!但它确实显示了使用固定宽度无符号类型的优雅。

【讨论】:

  • 对我来说也不是,但&lt;&lt; 32 会造成麻烦。
  • @unwind:再想一想,_n_m 的意图最好用你的方式表达。改了。
【解决方案5】:

这个怎么样?

#include <stdio.h>
#include <math.h>

long GetReverse(unsigned long n){
    if (n < 10){
        return n;

    } else {
        unsigned long r = GetReverse(n / 10);          
        int p = snprintf(NULL, 0, "%lu", r);    
        return lround(pow(10, p)) * (n % 10) + r; 
    }
}

int main(void){
    unsigned long n = 112233445566778899;   
    printf("%lu", GetReverse(n));   
    return 0;
}

【讨论】:

  • @sagi 啊,德克萨斯州。这很有趣。您是否允许使用多个功能;您是否允许使用 logpowlround 等数学函数?静态变量呢?
【解决方案6】:

要先放置最后一位数字,您需要将数字中的每个数字乘以 10:

#include <math.h>

long GetReverse(unsigned long n)
{
    if (n < 10)
        return n;  // Removed the % 10 as it is not needed when n is < 10
    else {
        long digit = n%10;
        long factor = (long) pow(10, (int)log(n));
        return  digit * factor + GetReverse(n / 10);
    }
}

使用logpow 代替循环来计算n 中的位数。注意this may fail 除非pow 的实现足够好。我使用 gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) 进行了测试,该组合对 10 的整数幂产生了正确的结果,结果符合 long

【讨论】:

  • 我认为 OP 知道如何处理循环和附加变量,所以它没有任何意义。
  • @achal 将循环替换为 math.h 中的 log/pow 函数。
  • @Bathsheba 在这种情况下,我想要,不需要,截断。
  • C 语言中的pow 甚至对于很小的整数参数也可能下冲。
  • @KlasLindbäck:可以。由于 pow(x, y) 经常被实现为 exp(y log x)
【解决方案7】:

没有循环,没有变量,没有额外的参数!


#include <stdio.h>
unsigned long reverse(unsigned long num)
{
if (num < 10) return num;
if (num < 100) return 10 * (num %10) + reverse(num/10);
if (num < 1000) return 100 * (num %10) + reverse(num/10);
if (num < 10000) return 1000 * (num %10) + reverse(num/10);
if (num < 100000) return 10000 * (num %10) + reverse(num/10);
if (num < 1000000) return 100000 * (num %10) + reverse(num/10);
if (num < 10000000) return 1000000 * (num %10) + reverse(num/10);
if (num < 100000000) return 10000000 * (num %10) + reverse(num/10);
return 100000000 * (num %10) + reverse(num/10);
}

int main(int argc, char **argv)
{
unsigned long num, rev;

if (argc < 2) return 1;
sscanf(argv[1], "%lu", &num);

rev = reverse(num);
printf("%lu -->> %lu\n", num, rev );

return 0;
}

或者,使用辅助函数(不是变量)

[注意:这具有二次复杂度(在位数上)]


unsigned long tencount(unsigned long num)
{
if (num < 10) return 1;
return 10 * tencount( num/10);
}

unsigned long reverse2(unsigned long num)
{
if (num < 10) return num;
return tencount(num) * (num %10) + reverse2(num/10);
}

【讨论】:

  • 不需要便携。它一直工作到溢出为止。 (您可以通过调用两次来检查溢出,并将第二个结果与原始结果进行比较)
【解决方案8】:

假设 32 位长,您可以在没有循环或递归的情况下完成;

long GetReverse(unsigned long n)
{
    unsigned long x = ((n/1000000000) +
                      ((n/100000000)%10)*10 +
                      ((n/10000000)%10)*100 +
                      ((n/1000000)%10)*1000 +
                      ((n/100000)%10)*10000 +
                      ((n/10000)%10)*100000 +
                      ((n/1000)%10)*1000000 +
                      ((n/100)%10)*10000000 +
                      ((n/10)%10)*100000000 +
                      ((n)%10)*1000000000);

    return (x/(9*(x%10==0)+1)/
            (9*(x%100==0)+1)/
            (9*(x%1000==0)+1)/
            (9*(x%10000==0)+1)/
            (9*(x%100000==0)+1)/
            (9*(x%1000000==0)+1)/
            (9*(x%10000000==0)+1)/
            (9*(x%100000000==0)+1)/
            (9*(x%1000000000==0)+1));
}

【讨论】:

    【解决方案9】:

    这是一个解决方案:

    int reverse(int i) {
        static int p = 0;
        if (i==0) { int r = p; p = 0; return r; }
        p = 10*p+i%10;
        return reverse(i/10);
    }
    

    想法是使用第二个参数,但由于它仅用于存储部分结果,因此可以使用静态变量。为了能够重用该函数,您只需在递归结束时重置静态。

    注意这样的函数不是对合意味着reverse(reverse(x))不等于x,想想x=1000。如果你想要对合,那么你需要在一个代表值的 C 字符串上定义它。

    【讨论】:

      【解决方案10】:

      C 递归地反转一个数字

      我有一个任务是创建一个接收数字并返回反转数字的函数。
      不允许循环,输入只是数字。

      添加辅助递归函数。 @Art
      无需静态变量,无需浮点数学运算。

      以下满足目标:
      1) 使用递归。
      2) 函数接收一个数字并返回反转后的数字
      3) 不允许循环,只输入数字

      #include <stdio.h>
      #include <stdlib.h>
      
      static unsigned reverse_helper(unsigned x, unsigned *pow10) {
        if (x < 10) {
          *pow10 = 10;
          return x;
        }
        unsigned y = reverse_helper(x / 10, pow10);
        y += *pow10 * (x%10);
        *pow10 *= 10;
        return y;
      }
      
      unsigned reverse(unsigned x) {
        unsigned pow10 = 1;
        unsigned y = reverse_helper(x, &pow10);
        printf("%10u %10u\n", x, y);
        return y;
      }
      
      int main(void) {
        reverse(0);
        reverse(9);
        reverse(10);
        reverse(99);
        reverse(100);
        reverse(1234);
        reverse(123456789);
      }
      

      输出

               0          0
               1          1
               9          9
              10          1
              99         99
             100          1
            1234       4321
       123456789  987654321
      

      【讨论】:

        【解决方案11】:

        像 OP 这样的解决方案使用 2 个递归函数。

        带 1 个参数、无浮点、无静态变量的递归函数。

        // return the great power-of-10 less than n
        unsigned long p10(unsigned long n) {
          if (n < 10) {
            return 1;
          }
          return p10(n/10) * 10;
        }
        
        unsigned long GetReverse(unsigned long n) {
          if (n < 10) {
            return n;
          }
          // OPs code
          //return  10 * GetReverse(n / 10) + n % 10;
        
          //     v----------------v------------------- scale by 1
          //     |                |   v-----------v--- scale by a power of 10 <= n
          return GetReverse(n / 10) + p10(n)*(n%10);
        }
        

        【讨论】:

          【解决方案12】:

          调用像char* getReverse(int n) 这样的函数怎么样?所以你可以使用 mod 和连接来获得相反的结果。然后在调用方方法int getReverse(int n) 中将字符串解析为int。您可以使用递归,然后使用单行进行解析。无需循环,只需一个参数。

          【讨论】:

            【解决方案13】:

            这是我完全可重入的版本,没有额外的变量。它的工作原理是使用ldiv( num / 10 ) 获得商和余数,然后返回乘以 10^(商中的位数)的余数加上商的倒数(代码被格式化以删除滚动条 - 通常我会有空白行和更多大括号):

            #include <stdlib.h>
            #include <stdio.h>
            #include <math.h>
            /* unsigned long power function */
            unsigned long lpow( unsigned long base, unsigned long exp )
            {
                unsigned long result = 1UL;
                while ( exp )
                {
                    if ( exp & 1 )
                        result *= base;
                    exp >>= 1;
                    base *= base;
                }
                return( result );
            }
            
            /* count the number of decimal digits */    
            unsigned long numdigits( unsigned long num )
            {
                return( floor( log10( num ) ) + 1 );
            }
            
            unsigned long reverse( unsigned long in )
            {
                ldiv_t tmp = ldiv( in, 10UL );
                if ( tmp.quot == 0 )
                    return( tmp.rem );
                return( reverse( tmp.quot ) + tmp.rem * lpow( 10, numdigits( tmp.quot ) ) );
            }
            

            unsigned long lpow() 函数来自https://stackoverflow.com/a/101613/4756299

            unsigned long numdigits() 函数来自https://stackoverflow.com/a/1068870/4756299

            这样称呼:

            int main( int argc, char **argv )
            {
                for ( int ii = 1; ii < argc; ii++ )
                {
                    unsigned long num = strtoul( argv[ ii ], NULL, 10 );
            
                    printf( "Reverse of %lu is %lu\n", num, reverse( num ) );
                }
            
                return( 0 );
            }
            

            【讨论】:

              【解决方案14】:

              对于初学者来说,不清楚为什么返回类型声明为 long 而参数的类型为 unsigned long

              long GetReverse(unsigned long n);
              ^^^^            ^^^^^^^^^^^^^
              

              要拥有更大的整数,最好声明参数和返回类型,如unsigned long long int

              可以使用局部静态变量来定义函数,该变量将保留计算出的反转值。

              在这里。

              unsigned long long int GetReverse(unsigned long long int n)
              {
                  const unsigned long long int Base = 10;
                  static unsigned long long int reversed;
              
                  unsigned long long int tmp;
              
                  reversed = Base * reversed + n % Base;
              
                  return (n /= Base ) == 0 ? tmp = reversed, reversed = n, n = tmp, n
                                           : GetReverse(n);
              }
              

              在下面的演示程序中,显示了该函数的工作原理。

              #include <stdio.h>
              
              unsigned long long int GetReverse(unsigned long long int n)
              {
                  const unsigned long long int Base = 10;
                  static unsigned long long int reversed;
              
                  unsigned long long int tmp;
              
                  reversed = Base * reversed + n % Base;
              
                  return (n /= Base ) == 0 ? tmp = reversed, reversed = n, n = tmp, n
                                           : GetReverse(n);
              }
              
              int main(void) 
              {
                  const unsigned long long int Base = 10;
              
                  for ( unsigned long long int i = 1, n = 0; i < Base; i++ )
                  {
                      n = Base * n + i;
              
                      printf( "%llu\n", n );
                      printf( "%llu\n", GetReverse( n ) );
                      putchar( '\n' );
                  }
              
                  return 0;
              }
              

              程序输出是

              1
              1
              
              12
              21
              
              123
              321
              
              1234
              4321
              
              12345
              54321
              
              123456
              654321
              
              1234567
              7654321
              
              12345678
              87654321
              
              123456789
              987654321
              

              【讨论】:

                猜你喜欢
                • 2014-04-03
                • 2013-02-12
                • 2012-10-20
                • 2012-12-14
                • 1970-01-01
                • 2012-01-13
                • 1970-01-01
                • 1970-01-01
                • 2014-06-10
                相关资源
                最近更新 更多