解决FizzBuzz的最具性能友好的方法



我在CodingBat上做这个FizzBuzz练习;

给定字符串str,如果字符串以"f"开头,则返回"Fizz"。如果字符串以"b"结尾,则返回"Buzz"。如果"f"one_answers"b"条件都成立,则返回"FizzBuzz"。在所有其他情况下,返回字符串时保持不变。

并给出了这个答案;

public String fizzString(String str)
{
    String sum = "";
    if (str.startsWith("f")) sum += "Fizz";
    if (str.endsWith("b")) sum += "Buzz";
    return (sum == "") ? str : sum;
}

然而,这个问题的作者还是选择了;

public String fizzString(String str)
{
    if (str.startsWith("f") && str.endsWith("b")) return "FizzBuzz";
    if (str.startsWith("f")) return "Fizz";
    if (str.endsWith("b")) return "Buzz";
    return str;
}

这似乎太多余了。。。

我想知道,在现实世界中,从性能角度来看,选择第一个节目而不是第二个节目会有什么不同吗?

我的计算表明情况并非如此。。。(评论区太拥挤了。)

我有一个java程序,它将在设定的时间(1000毫秒)内尽可能快地运行一块代码。它将这样做10次,以获得平均值、最小值和最大值。

我不得不说,第一种方法的速度更快,平均每秒大约有4000000个循环。

以下是我的结果:

   First Method:
Least loops: 26,312,768
Most loops: 26,918,157
Average loops: 26,582,653.7
   Second Method:
Least loops: 22,039,592
Most loops: 22,596,476
Average loops: 22,424,598.5

这是我的源代码,请告诉我我得到的数据可能有偏差。我保持计算机的负载不变,代码也保持不变。唯一改变的是我在while循环中调用的内容。

package personal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SpeedTest {
  public static void main(String[] args) {
    int loops = 10;
    double DELAY = 1000;
    int i;
    double[] loopCount = new double[loops + 1];
    double sum = 0;
    for (i = 0; i < loops + 1; i++) {
      long startTime = System.currentTimeMillis();
      long endTime = (long)(startTime + DELAY);
      long index = 0;
      while (true) {
        fizzString("TEST");
        //fizzString2("TEST");
        long now = System.currentTimeMillis();
        if (now >= endTime) {
          break;
        }
        index++;
      }
      if (i != 0) {
        if (DELAY != 1000) {
          if (DELAY / 1000 % 1 == 0) {
            System.out.printf("Test %.0f. %,.0f loops in %.0f seconds.n", (float) i, (float) index, (float) DELAY / 1000);
          } else if ((DELAY / 100) % 1 == 0) {
            System.out.printf("Test %.0f. %,.0f loops in %.1f seconds.n", (float) i, (float) index, (float) DELAY / 1000);
          } else if ((DELAY / 10) % 1 == 0) {
            System.out.printf("Test %.0f. %,.0f loops in %.2f seconds.n", (float) i, (float) index, (float) DELAY / 1000);
          } else if (DELAY % 1 == 0) {
            System.out.printf("Test %.0f. %,.0f loops in %.3f seconds.n", (float) i, (float) index, (float) DELAY / 1000);
          }
        } else {
          System.out.printf("Test %.0f. %,.0f loops in %.0f second.n", (float) i, (float) index, (float) DELAY / 1000);
        }
        loopCount[i] = index;
      }
    }
    Arrays.sort(loopCount);
    System.out.printf("Least loops: %,.0fn", (loopCount[1]));
    System.out.printf("Most loops: %,.0fn", loopCount[loops]);
    for (int d = 1; d < loopCount.length; d++) {
      sum += loopCount[d];
    }
    double averageLoopCount = 1.0f * sum / (loopCount.length - 1);
    System.out.printf("Average loops: %,.1f", averageLoopCount);
  }
  public static String fizzString(String str) {
    if (str.startsWith("f") && str.endsWith("b")) return "FizzBuzz";
    if (str.startsWith("f")) return "Fizz";
    if (str.endsWith("b")) return "Buzz";
    return str;
  }
  public static String fizzString2(String str) {
    String sum = "";
    if (str.startsWith("f")) sum += "Fizz";
    if (str.endsWith("b")) sum += "Buzz";
    return (sum == "") ? str : sum;
  }
}

自己试试:)

这实际上取决于实际执行的CPU指令,

但总的想法是有

  • 执行的分支数最少(如果为else)
  • 内存访问次数最少
  • 没有动态分配

这样的解决方案应该比这两种方案都快。

public String fizzString(String str)
{
    if (str.length() == 0) return str;
    if (str.charAt(0) == 'f') {
        if (str.charAt(str.length() - 1) == 'b') {
            return "FizzBuzz";
        }
        return "Fizz";
    }
    if (str.charAt(str.length() - 1) == 'b') {
        return "Buzz";
    }
    return str;
}

相关内容

最新更新