JAVA:来自codechef

时间:2016-06-23 07:05:28

标签: java performance

所以今天我从Codechef解决了一个非常简单的问题,我用JAVA解决了问题,我的答案被接受了。我的代码是。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


class INTEST {
    public static void main(String args[]) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String input = reader.readLine();
        int n = Integer.parseInt(input.split(" ")[0]);
        long k = Long.parseLong(input.split(" ")[1]);
        int count = 0;
        String element;
        for (int i = 0; i < n; i++) {
            element = reader.readLine();
            if (Long.parseLong(element) % k == 0) {
                count++;
            }
        }
        System.out.println(count);
    }
}

onine法官报告

  • 运行时间:0.58秒
  • 记忆:1340.5M

所以,我针对同样的问题研究了其他一些解决方案(按时间对解决方案进行了排序),我得到了用户 indontop 的另一种解决方案。

public class Main{

    public static void main(String ...args)throws Exception{

        byte b;
        byte barr[]=new byte[1028];
        int r=0,n=0,k=0;
        while((r=System.in.read())!= ' '){
            n=n*10+r-'0';

        }
        //System.out.println(n);

        while((r=System.in.read())!='\n'){          //change
            k=k*10+r-'0';

        }

        //System.out.println(k);
        //System.in.read();             // remove
        n=0;
        int count=0;
        while((r=System.in.read(barr,0,1028))!=-1){

            for(int i=0;i<barr.length;i++){

                b=barr[i];

                if(b!='\n'){            //change

                    n=n*10+b-'0';                   

                }

                else{

                //  i++;            //remove
                    if(n%k==0)count++;
                    n=0;                                        

                }
            }


        }       
        System.out.println(count);


    }



} 

上述代码的执行时间和内存。

  • 运行时间:0.13秒
  • 记忆:OM

我想知道用户如何通过这个非常简单的问题实现这么多的性能和内存增益。

我不明白这段代码背后的逻辑,任何人都可以通过解释这段代码来帮助我,还请解释我的代码有什么问题。

谢谢。

1 个答案:

答案 0 :(得分:1)

indontop 如何实现更好的内存占用

基本上, indontop 程序直接从输入流中读取字节,而不通过读取器或读取线。它分配的唯一结构是一个1028字节的单个数组,没有其他对象直接创建。

另一方面,您的程序会从BufferedReader读取行。每个这样的行在内存中被分配为字符串。但是你的程序相当短,因此垃圾收集器很可能没有启动,因此所有读取的行都不会从内存中清除。

indontop 的程序

它逐字节读取输入并直接从中解析数字,而不使用Integer.parseInt或类似的方法。通过从每个字符中减去'0',可以将字符'9''0'转换为各自的值(0-9)。通过注意'123'之类的数字可以解析为1*10*10 + 2*10 + 3来解析数字本身。

最重要的是,用户正在实现解释数字的基本算法,而不会在内存中使用完整的字符串。

indontop 的程序比你的好吗?

我对此的回答是否定的。首先,他的程序并不完全正确:他正在读取一个字节数组,而不是检查实际读取的字节数。最后一个数组读取可以包含上一次读取的字节,这可能会产生错误的输出,而且运气好的话,这并没有发生。

现在,其余部分是基于意见的:

  • 你的程序比他的程序更具可读性。你有有意义的变量名,他没有。你使用的是众所周知的方法,但他并没有。你的代码简洁,冗长,并且多次重复相同的代码。
  • 他正在重新发明轮子 - 在Java中有很多解析方法,不需要重写它们。
  • 就系统调用而言,逐字节读取数据效率很低,并且仅在CodeChef等类似站点的人工环境中提高效率。

运行时效率

你真的不能通过观察一次跑来说出来。这些程序在共享服务器下运行,该服务器执行许多其他操作,并且有太多因素会影响性能。基准测试是一个复杂的问题。你看到的数字?只是忽略它们。

过早优化

在现实世界的程序中,内存在需要时进行垃圾回收。只有当它非常明显时才能提高内存效率(如果你打算只使用1000个字节,不要分配1000000字节的数组),或者当程序在真实条件下运行时,记忆问题。

对于时间效率也是如此,但正如我所说,如果他的程序比你的程序更有效,那么它甚至都不清楚。

你的节目好吗?

嗯,不完美,你运行拆分两次,最好只做一次并将结果存储在一个双元素数组中。但除此之外,这个问题的答案很好。