【问题标题】:Java FizzBuzz recursive solutionJava FizzBu​​zz 递归解决方案
【发布时间】:2018-12-09 21:56:15
【问题描述】:

尝试在 Java 中使用 FizzBu​​zz 递归解决方案以返回具有 n 次迭代的字符串列表。例如,n = 4 应该输出 ["1","2","Fizz", 4]。但是,使用我当前的代码,输出只是 ["4"]。为什么我的解决方案不执行递归函数?任何其他批评表示赞赏!

class Solution {
public List<String> fizzBuzz(int n) {

    //create variable to return list of strings
    List<String> fbList = new ArrayList<String>();

    //base case 1
    if(n == 0){
        fbList.add(Integer.toString(0));
    }

    //base case 2
    else if(n == 1){
        fbList.add(Integer.toString(1));
    }    

    //OW take n and begin reducing recursively from, n - 1
    else{
        if(n % 3 == 0){
            fbList.add("Fizz");
        }
        else if(n % 5 == 0){
            fbList.add("Buzz");
        }
        else if((n % 3 == 0) && (n % 5 == 0)){
            fbList.add("FizzBuzz");
        }
        else{
            fbList.add(Integer.toString(n));
        }
        //recursive function call
        fizzBuzz(n - 1);
    }
    return fbList;
    }
}

【问题讨论】:

  • 看来你需要学习使用调试器了。请帮助自己一些complementary debugging techniques。如果您之后仍有问题,请随时回来提出更具体的问题。
  • 您可能希望首先在您的if-statement 中运行else if((n % 3 == 0) &amp;&amp; (n % 5 == 0)){ fbList.add("FizzBuzz"); }

标签: java algorithm list recursion fizzbuzz


【解决方案1】:

问题是每次递归调用都会创建一个新的List。您返回列表但是:

fizzBuzz(n - 1);

您忽略了递归调用的返回值。要解决此问题,您可以这样做:

fbList.addAll(0, fizzBuzz(n - 1));

它将利用addAll 方法添加递归调用返回的所有元素。这返回:

[1, 2, Fizz, 4]

然而,这对于ArrayList 来说相当昂贵。您可以将其更改为 LinkedList,这将允许线性时间添加。


另外你if/else if/else 链坏了。 if((n % 3 == 0) &amp;&amp; (n % 5 == 0)) 应该在 if(n % 3 == 0)if(n % 5 == 0) 之前。否则会一直输入if(n % 5 == 0)if(n % 3 == 0)

if((n % 3 == 0) && (n % 5 == 0)){
    fbList.add("FizzBuzz");
}
else if(n % 3 == 0){
    fbList.add("Fizz");
}
else if(n % 5 == 0){
    fbList.add("Buzz");
}

【讨论】:

  • 这允许我输出值 ["4", "Fizz", "2", "1"]。我猜这个解决方案只会按降序输出。有没有办法按升序输出?
  • @alexjs000 以相反的顺序追加或反转整个结果。
  • 想将复杂度保持在 O(n),不使用函数来反转整个顺序使其成为 O(n^2)?
  • @alexjs000 可以使用重载的addAll方法添加到开头
  • @alexjs000 不,在每一步(总共 n 次)预先添加到不是为该操作设计的数据结构(ArrayList)(即它与已包含的元素数量呈线性关系)将使它O(n^2)LinkedList 在前面是线性的。
【解决方案2】:

使用递归时要考虑简单,即让递归完成工作。如果您的递归正在倒计时,但您希望列表按升序排列,请先添加 其他所有内容,然后添加您正在处理的内容:

import java.util.*;

public class Solution {

    public static List<String> pattern = Arrays.asList("FizzBuzz", "", "", "Fizz", "", "Buzz", "Fizz", "", "", "Fizz", "Buzz", "", "Fizz", "", "");

    public static List<String> fizzBuzz(int n) {

        List<String> fbList;

        if (n > 0) {
            fbList = fizzBuzz(n - 1);
            String string = pattern.get(n % pattern.size());
            fbList.add(string.isEmpty() ? Integer.toString(n) : string);
        } else {
            fbList = new ArrayList<String>();
        }

        return fbList;
    }

    public static void main(String[] args) {
        System.out.println(fizzBuzz(Integer.parseInt(args[0])));
    }
}

输出

> java Solution 35
[1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, FizzBuzz, 31, 32, Fizz, 34, Buzz]
> 

【讨论】:

  • 这是一个非常低效的O(n^2),因为您在每一步都再次复制整个列表。
  • 不一定。有许多更有效的选项:您可以使用具有高效前置的 LinkedList,您可以以相反的顺序收集到 ArrayList,然后在 O(n) 中反转数组,或者您可以将结果 ArrayList 作为参数传递。所有这些方法都将是O(n)
  • @LieRyan,谢谢,我已将解决方案修改为仅使用单个 ArrayList。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
相关资源
最近更新 更多