【问题标题】:Small Java app performance小型 Java 应用程序性能
【发布时间】:2017-07-12 23:08:50
【问题描述】:

我有一个用于我的 CS 课程的程序,当我得到大量输入时,我需要将运行时间缩短很多。

这里是代码

import java.util.Scanner;
import java.util.ArrayList;

public class Main{
    public static void main (String[] args){


    Scanner input = new Scanner(System.in);


    int hours = 12;
    int minutes = 00;

    int count = 0;

    int d = input.nextInt();

    for(int i = 0; i < d; i++){
        minutes++;
        if(minutes >= 60){
            hours++;
            hours = hours % 12;
            minutes = 0;
        }

        String formatNull = "";
        String hourFormat = "";

        if(minutes < 10){
            formatNull = "0";
        }

        if(hours < 10)
            hourFormat = "0";

        String finalTimeString = hourFormat + hours + ":" + formatNull + minutes;

        if(isSequence(finalTimeString)){
            count += 1;

        }

    }

    System.out.println(count);

}

public static boolean isSequence(String time){

    String firstDig = time.split(":")[0];
    String secondDig = time.split(":")[1];



    ArrayList<Integer > foo = new ArrayList<Integer>();

    if(firstDig.length() >= 2){
 if(firstDig.charAt(0) != '0'){
        foo.add(Integer.parseInt(String.valueOf(firstDig.charAt(0))));
    }   foo.add(Integer.parseInt(String.valueOf(firstDig.charAt(1))));
    }

    if(secondDig.length() >= 2){
        foo.add(Integer.parseInt(String.valueOf(secondDig.charAt(0))));
        foo.add(Integer.parseInt(String.valueOf(secondDig.charAt(1))));
    }

    ArrayList<Integer> bar = new ArrayList<Integer>();

    int prev = foo.get(0);


    for(int i = 1; i < foo.size(); i++){


     bar.add(foo.get(i) - prev);
        prev = foo.get(i);
     }




    boolean isDiff = false;

    int prevDifference = bar.get(0);

    for(int i = 1; i < bar.size(); i++){
        if(prevDifference == bar.get(i)){

        }else{

            isDiff = true;

        }

        prevDifference = bar.get(i);

    }

    return !isDiff;

}

}

我不能超过 0.8 秒,现在我达到了 2.0 秒。如果有人可以提出任何建议,那就太好了。干杯。

//更新所以我想我现在正确地格式化了代码。该程序以分钟为单位接受输入,将其添加到 12 点钟并计算有多少特殊时间。一个特殊的时间例如:12:43、02:46(本质上是数字有共同点的时间);

【问题讨论】:

  • 提示:您希望我们花时间帮助您完成作业。因此,至少要花时间正确格式化/缩进所有您的输入,除此之外:解释您的程序到底在做什么;以及您在哪里优化它。这不是免费的家教服务!
  • “如果有人可以提出任何建议......” 这是关于 SO 的题外话。它既太模糊了,也要求推荐一种算法/策略来修复。两者都是题外话
  • 如果您的代码给出了正确的结果并且您希望对其进行改进,那么在 (Code Review)[codereview.stackexchange.com/] 网站上提供它可能会更好。但是,如果您正在寻找另一种算法,您应该重新表述您的问题。
  • @GhostCat 我很久以前学到的一件事(至少我尝试过)是:不要考虑其他人的投票方式。太多的用户不关心这个网站的目的(“高质量的问题”咳嗽),或者只是不打扰和赞成任何有一些英文单词和格式化为代码的东西。这就是我使用自定义 CSS 样式隐藏所有投票的原因。有了这个,这个网站变得更好了。
  • 感谢 AntonH 会做的!

标签: java performance processing-efficiency


【解决方案1】:

我马上注意到的几件事:

首先,您在循环中调用isSequenceisSequence 本身有两个循环。因此,这个算法是O(d * (foo.size() + bar.size())。事实上,我们实际上可以说它是Theta(d * (foo.size() + bar.size())(即总是那么复杂),因为它实际上不可能少于d * (foo.size() + bar.size()) 步骤。 (作为记录,是的,我确实意识到我的符号并不严格准确,因为 n 的倍数只是减少到 n,但我想把它写出来这种方式很有用)。这可能是大输入速度慢的主要原因之一。您可能需要考虑尝试减少这种情况的方法。

我的意思是,如果你的底层算法的计算复杂度太高,你在代码优化方面只能做这么多。

其次,作为优化:

for(int i = 1; i < bar.size(); i++){
    if(prevDifference == bar.get(i)){
       // You don't actually do anything here
    }else{
        // Why not break out the loop here? There's no possibility of this
        // becoming false later. That could save you some steps.
        isDiff = true;
    }

    prevDifference = bar.get(i);
}

最后,为什么你不能在isSequence 中组合你的 for 循环?

【讨论】:

  • Foo 和 bar 很小,我想。最多4个。因此,从中获得的收益也将微乎其微。 (但这并不意味着它们不应该被实施。)
  • @DM 是的,我认为你是对的。但即使他们都是 4,那仍然是 8d 操作。
【解决方案2】:

免责声明:据我所知,您的代码目前给出了错误的答案。你需要解决这个问题。但是你问的是如何让它运行得更快,而不是如何修复它,所以这就是我要回答的问题。

您正在执行大量字符串格式化和解析,其中很多都在您的主循环中。你从 String 到 int 再从 int 到 String 多少次?所有这些来回转换都会显着减慢速度。

如果您的分钟数是 2 位数,您可以使用 minutes % 10 获取最后一位数。您可以使用minutes / 10 获取第一位数字。时间也是一样。不需要字符串解析。这已经足以将时间降低到所需的时间以下。

但您还可以做一些更好的事情。您可以让它在有效的 O(1) 时间内运行,而不是让您的代码在 O(n) 时间内运行。是的,你没看错。对于较大的 n,您可以使其在恒定时间内运行。

请注意,一天中小时和分钟的可能组合只有这么多。如果您使用 12 小时时间,则 12*60 = 720。您可以利用这一点。您只需要处理 720 的答案和n % 720 的答案,然后做一些数学运算。 answer(n)answer(720) * n/720 + answer(n % 720)。使用它,您可以或多或少地立即计算出任何高达 2147483647 的值。哎呀,如果您使用 long 而不是 int,您可以或多或少地立即计算出高达 9223372036854775807 的任何值。(想想看 - 72000000 的答案正在发生正好是 720 答案的 100000 倍,因为相同的数字只是重复,所以为什么还要循环 72000000 次呢?)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 2012-09-10
    • 2011-05-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    相关资源
    最近更新 更多