最有效的算法,用于在一组4个数字中查找最多出现的数字

时间:2012-10-28 20:48:27

标签: java algorithm byte

我正在逐字节地读取四个文件,并比较所有这四个字节,从这四个字节中得到一个最后一个字节。它的工作方式是:

  1. 如果所有字节均为0,则输出0
  2. 如果除1个字节以外的所有字节都是0,则输出奇数字节输出(如果字节为0, 0, 1, 0,那么我将输出1
  3. 如果2个字节是0,那么我随机输出一个非0字节
  4. 如果1个字节是0,那么我从其他3个字节输出最多的字节,否则在出现平局的情况下我从该集合输出一个随机字节
  5. 如果所有字节都是非0,那么我输出最多的字节,否则在出现平局的情况下我会从该集输出一个随机字节
  6. 需要注意的一点是,“随机”并不是随机的,我可以选择最方便的。

    所以我已经考虑了一些,但我仍然无法想出从这些数字中获取输出的绝对最快的方法。我注意到的一件事是,如果我读取的前两个字节是相同且非零,那么我可以跳过接下来的两个字节,只输出前两个字节中的一个。如果前三个字节是0,那么我可以输出最后一个字节。我还可以检查第一个字节和第二个字节的第三个字节,看看它们是否相等,这样我就可以避免进入第4个字节,但我需要这个字体尽可能高效。我需要在这个算法上运行大约80亿次,所以每一点都要计算=)

    无论如何,最有效的方法是什么? (伪代码?或其他)

    这就是程序的样子(至少它的外壳):

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class reconstructerv2 {
       public static void main(String[] args) throws IOException {
    
          FileInputStream in1 = null;
          FileInputStream in2 = null;
          FileInputStream in3 = null;
          FileInputStream in4 = null;
          FileOutputStream out = null;  
    
          try {
             in1 = new FileInputStream("1.dd");
             in2 = new FileInputStream("2.dd");
             in3 = new FileInputStream("3.dd");
             in4 = new FileInputStream("4.dd");
             BufferedInputStream in1b = new BufferedInputStream(in1);
             BufferedInputStream in2b = new BufferedInputStream(in2);
             BufferedInputStream in3b = new BufferedInputStream(in3);
             BufferedInputStream in4b = new BufferedInputStream(in4);
             out = new FileOutputStream("final.dd");
             int a;
             int b;
             int c;
             int d;
             int o; 
    
             while ((a = in1.read()) != -1) {
                b = in2.read();
                if (a == b && a != 0)
                   o = a;
                else {
                   c = in3.read();
                   d = in4.read();
                }
                System.out.println((byte) c);
                out.write((byte) o);
             }
          } finally {
             if (in1 != null) {
                in1.close();
                in2.close();
                in3.close();
                in4.close();
             }
             if (out != null) {
                out.close();
             }
          }
       }
    }
    

    编辑:80亿,而不是800万

    EDIT2:正如评论中所指出的,由于同步,我不能跳过阅读字符。

2 个答案:

答案 0 :(得分:1)

  

如果所有字节都为0,则输出0

输出a + b + c + d。

  

如果除1字节以外的所有字节都为0,则输出奇数字节输出(如果字节为0,0,1,0,那么我将输出1)

与上述相同。这已经为您节省了一个案例。如果任何三个字节为零,则输出总和。

  

如果2个字节为0,则我随机输出一个非0字节   如果1个字节是0,那么我从其他3个字节输出最多的字节,否则在连接的情况下我从该组输出一个随机字节   如果所有字节都是非0,那么我输出最多出现的字节,否则在出现平局的情况下我输出该集合中的随机字节

这些案件实际上都是一样的。输出最多出现的非零字节,或者在出现平局时输出随机字节。

因此,实际上只有两种情况需要考虑:至少三个零字节,两个或更少。

事实上所有案件都是相同的。您可以将上面的第二个解决方案应用于所有案例。最好不要将它们分开。

但首先在那些FileInputStreams周围添加了BufferedInputStreams。

答案 1 :(得分:1)

这个while循环不起作用:

while ((a = in1.read()) != -1) {
    b = in2.read();
    if (a == b && a != 0)
        o = a;
    else {
        c = in3.read();
        d = in4.read();
    }
    System.out.println((byte) c);
    out.write((byte) o);
}

因为有时你会读取file1和file2,有时你会读取所有四个文件。

另一点:当你读取所有四个文件时o未设置或具有前一轮的值。如果您只读取file1和file2,这也适用于c。因此,为了解决这个问题,总是必须读取所有四个文件,然后循环的性能并不重要。