【问题标题】:Printing a number in sequence using C - Algorithm使用 C 算法按顺序打印一个数字
【发布时间】:2015-09-20 09:29:24
【问题描述】:

给出了示例模式,

input :    16
output:    16 11 6 1 -4 1 6 11 16

如果输入是 10,那么程序应该打印输出为

10 5 0 5 10

注意:以上序列按 5 递减/递增。

挑战在于不声明任何变量或循环。只使用递归。

我已尝试使用以下代码。

void sequence(int input, int base){

    input = input - (input > 0?5:-5); //main execution
    printf("input:%d\n",input);
    if(input == base)return;
    sequence(input,base);
}

//例如。 input 和 base(initial Value) 为 16。上述方法自身递归,直到 input = base。

我可以打印到这个序列(粗体)

16 11 6 1 -4 1 6 11 16

如何完成序列。在上述方法中,在主执行行中,我需要检查条件为input = input - (input < 0?5:-5); 以打印剩余的序列。但我不确定如何在没有任何变量或循环的情况下做到这一点。是否有任何可用的算法或任何其他更好的解决方案。

【问题讨论】:

  • 需要左递归还是右递归?如果没有,只需在停止递归的测试后再次输出......顺便说一句,你永远不需要base 参数......到达递归的顶部框架就足够了。
  • 使用这些限制是不可能的。你必须使用变量,至少是“参数”。
  • @Olaf,这可能就是它说不要声明变量的原因。我也不会添加任何 mutate 。显然,目标是以“功能性”的方式做到这一点。我希望在这里展示解决方案不会破坏学习体验...
  • @FelixPalmen:没有声明参数? (顺便说一句。OP 很可能混淆了声明和定义;我没有看到仅仅声明一个变量有问题,因为在定义它之前你不能使用它......)
  • @Olaf 函数声明不是变量声明。是的,声明一个未在任何地方定义的变量不会干扰代码的功能性质,但这只是无用的——考虑一下这里真的很挑剔,对不起;)跨度>

标签: c algorithm recursion


【解决方案1】:

我的评论中的一些示例代码,如果它不必严格地左递归或右递归,它将匹配:

void sequence(int n)
{
    printf("%d ", n);
    if (n > 0)
    {
        sequence(n-5);
        printf("%d ", n);
    }
}

补充说明:

1.) 这似乎是关于函数式编程,其中一个关键概念是您永远不能分配变量...看看这里是如何避免的。 (严格来说,由于printf 的副作用,它不起作用)

2.) 它不是严格的左递归或右递归(意味着递归发生在评估的中间),因此它不能轻易地转换为迭代。

【讨论】:

  • 太棒了:短且有效!我为它做了一个life demo
  • 序列(-16)的输出可能是什么?
  • @kkk 只是-16。 OP 描述中没有指定这是否应该输出任何东西,这里它会...
  • @kkk 你最喜欢的输出对于 -16 是什么?
  • 这样的东西 -16 -11 -6 -1 4 -1 -6 -11 -16
【解决方案2】:

似乎递归应该在到达0 或以下时停止。所以在你的递归函数中试试这个条件(减少到只有一个参数):

void sequence(input) {
    // print input
    if (input > 0) {
        // recursive call
        sequence(input);
    }
    // print input again (sometimes...)
}

更新:让我们谈谈对称性

为了对称,Felix's solutionreverse version也可以用

void sequence(int n)
{
    if (n > 0) {
        printf("%d ", n);
        sequence(n-5);
    }
    printf("%d ", n);
}

两者都具有一种似乎不适合问题的回文结构的不对称性,并且还有另一个问题:尾随空格的缺陷。那么让我们向您介绍一个处理这些微小(?)缺陷的obvious solution

void sequence(int n)
{
    if (n > 0) {
        printf("%d ", n); sequence(n-5); printf(" %d", n);
    } else {
        printf("%d", n);
    }
}

【讨论】:

  • base 只是初始值。 16.
  • 这将打印两次中间(最小值)值;第二个打印语句应该放在if 正文中。
  • @MOehm 是的,我知道,这就是我在第二条评论中添加“(有时...)”的原因 ;-)
  • @Wolf 如果空格很重要,最后一个很好。当然它仍然不是 L 或 R 递归 ;)
【解决方案3】:

使用两个不同的函数来向上和向下计算:

void down(int input, int base) {
    printf("input:%d\n",input);
    if(input > 0) down(input - 5, base);
    else up(input + 5, base);
}

void up(int input, int base) {
    printf("input:%d\n",input);
    if(input == base) return;
    up(input + 5, base);
}

调用down开始计算。

Live Demo

【讨论】:

  • 嗯,当你从下降的递归函数返回时,你已经在上升了。
  • 不,看现场演示。
  • 是的,当然。你递归的深度是你需要的两倍。也许我的评论模棱两可;它不是指您的解决方案,它有效但不必要地长,而是指假定的解决方案,即在递归后有另一个打印步骤。
  • 是的,这是真的。但是这个答案表明可以通过调用另一个递归路径来替换变量,这有时很有用。 (这就是为什么我认为这个答案会增加价值。)
【解决方案4】:

您的递归代码的base case 似乎是错误的。我认为您的代码按原样进入无限递归。您可以使用标志来实现您的序列:

void sequence(int input, int base){
    static int flag = 0;
    //input = input - (input > 0?5:-5); //main execution, wrong
    printf("input:%d\n",input);
    input -= (flag == 0)?5:-5;          //use flag for base case of sequence
    if(input <= 0)
        flag = 1;
    if(input == base){
        printf("input:%d\n",input);
        return;
    }
    sequence(input,base);
}

【讨论】:

  • 不应使用变量(在问题中提到),使用标志也不是一个好习惯:)
  • 啊..是的。我使用了一个不符合 OP 条件的标志,但为什么你说使用标志是不好的做法?
  • 我的意思是高于 OP
【解决方案5】:
#include <stdio.h>

using namespace std;

void printSequence(int input) {
    printf("%d ", input);
    if (input <= 0)
        return;
    printSequence(input - 5);
    printf("%d ", input);
}

int main ()
{
    int input = 0;
    scanf("%d", &input);

    printSequence(input);

    return 0;
}

【讨论】:

    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    相关资源
    最近更新 更多