【问题标题】:Hailstone Sequence, recursive, missing the 1 case冰雹序列,递归,缺少1个案例
【发布时间】:2018-12-07 16:41:16
【问题描述】:

我有以下冰雹序列代码,它适用于所有数字,除了 1 的序列:

public class Recursion {
    public static void main(String[] args) {
        hailstone(16);  // prints  16 8 4 2 1
        hailstone(1);  //prints just 1 instead of 1 4 2 1
    }

    public static void hailstone(int seed) {
        String str = "" + seed;

        if (seed == 1) {
            System.out.print(str);
        } else {
            if (seed % 2 == 0) {
                System.out.print(str + " ");
                hailstone(seed / 2);
            } else {
                System.out.print(str + " ");
                hailstone((3 * seed) + 1);
            }
        }
    }
}

如何在递归方法和无效的情况下绕过这种特殊情况?

我不允许使用任何类型的循环。

【问题讨论】:

  • 代码正确。冰雹序列以 1 结束,如果这是第一个元素,则整个序列为 1。
  • 有人告诉我,如果种子是 1,那么这是一个特例
  • @NathanHughes from plus.maths.org/content/…: 似乎所有冰雹序列最终都以无限循环结束 [4, 2, 1, 4, 2, 1,...]。如果通过循环实现,这将导致无限循环,如果通过递归实现,则会导致堆栈溢出。因此,在第一个序列 [4, 2, 1] 之后的程序实现中,程序必须停止。

标签: java recursion sequence collatz


【解决方案1】:

1 是递归的出口点,这就是为什么你不能让它也表现得像一个入口点。
如果你改变出口点怎么办?将2 设为退出点:

public static void hailstone(int seed) {
    String str = "" + seed;

    if (seed == 2) {
        System.out.print(str + " 1");
    } else {
        if (seed % 2 == 0) {
            System.out.print(str + " ");
            hailstone(seed / 2);
        } else {
            System.out.print(str + " ");
            hailstone((3 * seed) + 1);
        }
    }
}

public static void main(String[] args) {
    hailstone(16);
    System.out.println();
    hailstone(15);
    System.out.println();
    hailstone(1);
    System.out.println();
}

将打印:

16 8 4 2 1
15 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1
1 4 2 1

【讨论】:

    【解决方案2】:

    最后一个小注释供您参考(我很惊讶地看到代码中的所有静态)。

    说到点子上了。你这么说:

    • 您不能更改签名
    • 您必须使用递归(不允许循环)

    定义一个静态布尔值并为达到数字 1 的情况添加一个条件。
    冰雹序列中的最后一个序列是无限模式。特殊情况是因为您需要程序在某个时刻停止。在这里,我只是在第一次达到数字 1 后使用布尔值打印一次模式。我希望代码是自我解释的。

    public class Recursion {
    
        private static boolean reached = false; 
    
        public static void main(String[] args) {
            //hailstone(16);  // prints  16 8 4 2 1
            hailstone(1);  //prints just 1 instead of 1 4 2 1
        }
    
        public static void hailstone(int seed) {
            String str = "" + seed;
    
            if (seed == 1 && reached) {
                System.out.print(str);
            } else if (seed == 1 && !reached) {
                System.out.print(str + " ");
                reached = true;
                hailstone((3 * seed) + 1);
            } else {
                if (seed % 2 == 0) {
                    System.out.print(str + " ");
                    hailstone(seed / 2);
                } else {
                    System.out.print(str + " ");
                    hailstone((3 * seed) + 1);
                }
            }
        }
    }
    

    注意:在 Java 中,编写大量静态成员/方法通常不是一个好习惯。我相信它可以设计得更好。我不想讨论这个,因为我不想混淆,我想专注于这个问题。
    例如,按照我的方式对其进行编码有一个缺点。只需尝试随后致电hailstone(16)hailstone(1),您就会明白我的意思;这是因为布尔值已经从第一个序列计算中设置。您需要再次将其重置为 false。有更好的方法来设计这个...

    【讨论】:

      猜你喜欢
      • 2019-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-06
      • 1970-01-01
      相关资源
      最近更新 更多