Java Array, Finding Duplicates

前端 未结 14 847
闹比i
闹比i 2020-11-22 09:13

I have an array, and am looking for duplicates.

duplicates = false;
for(j = 0; j < zipcodeList.length; j++){
    for(k = 0; k < zipcodeList.length; k++         


        
14条回答
  •  南笙
    南笙 (楼主)
    2020-11-22 10:02

    On the nose answer..

    duplicates=false;
    for (j=0;j

    Edited to switch .equals() back to == since I read somewhere you're using int, which wasn't clear in the initial question. Also to set k=j+1, to halve execution time, but it's still O(n2).

    A faster (in the limit) way

    Here's a hash based approach. You gotta pay for the autoboxing, but it's O(n) instead of O(n2). An enterprising soul would go find a primitive int-based hash set (Apache or Google Collections has such a thing, methinks.)

    boolean duplicates(final int[] zipcodelist)
    {
      Set lump = new HashSet();
      for (int i : zipcodelist)
      {
        if (lump.contains(i)) return true;
        lump.add(i);
      }
      return false;
    }
    

    Bow to HuyLe

    See HuyLe's answer for a more or less O(n) solution, which I think needs a couple of add'l steps:

    static boolean duplicates(final int[] zipcodelist)
    {
       final int MAXZIP = 99999;
       boolean[] bitmap = new boolean[MAXZIP+1];
       java.util.Arrays.fill(bitmap, false);
       for (int item : zipcodeList)
         if (!bitmap[item]) bitmap[item] = true;
         else return true;
       }
       return false;
    }
    

    Or Just to be Compact

    static boolean duplicates(final int[] zipcodelist)
    {
       final int MAXZIP = 99999;
       boolean[] bitmap = new boolean[MAXZIP+1];  // Java guarantees init to false
       for (int item : zipcodeList)
         if (!(bitmap[item] ^= true)) return true;
       return false;
    }
    

    Does it Matter?

    Well, so I ran a little benchmark, which is iffy all over the place, but here's the code:

    import java.util.BitSet;
    
    class Yuk
    {
      static boolean duplicatesZero(final int[] zipcodelist)
      {
        boolean duplicates=false;
        for (int j=0;j

    With NSQUARED:

    Trial for size= 10
    Size=10, avg time = 0.0ms
    Trial for size= 1000
    Size=1000, avg time = 0.0ms
    Trial for size= 10000
    Size=10000, avg time = 100.0ms
    Trial for size= 100000
    Size=100000, avg time = 9923.3ms
    

    With HashSet

    Trial for zipcodelist size= 10
    Size=10, avg time = 0.16ms
    Trial for zipcodelist size= 1000
    Size=1000, avg time = 0.15ms
    Trial for zipcodelist size= 10000
    Size=10000, avg time = 0.0ms
    Trial for zipcodelist size= 100000
    Size=100000, avg time = 0.16ms
    Trial for zipcodelist size= 1000000
    Size=1000000, avg time = 0.0ms
    

    With BitSet

    Trial for zipcodelist size= 10
    Size=10, avg time = 0.0ms
    Trial for zipcodelist size= 1000
    Size=1000, avg time = 0.0ms
    Trial for zipcodelist size= 10000
    Size=10000, avg time = 0.0ms
    Trial for zipcodelist size= 100000
    Size=100000, avg time = 0.0ms
    Trial for zipcodelist size= 1000000
    Size=1000000, avg time = 0.0ms
    

    BITSET Wins!

    But only by a hair... .15ms is within the error for currentTimeMillis(), and there are some gaping holes in my benchmark. Note that for any list longer than 100000, you can simply return true because there will be a duplicate. In fact, if the list is anything like random, you can return true WHP for a much shorter list. What's the moral? In the limit, the most efficient implementation is:

     return true;
    

    And you won't be wrong very often.

提交回复
热议问题