【问题标题】:Faster/Easier method of finding number of duplicates of values in an array查找数组中重复值数量的更快/更简单的方法
【发布时间】:2015-09-20 20:10:13
【问题描述】:

我目前使用HashMap 来对应重复值及其重复次数。它的linear efficiency O(n) 但我正在寻找一些内置方法或更快的方法来计算数组中每个值的重复数(如O(log n))?

这是我目前的有效镜头:

String[] array = {"Henry", "Henry", "Henry", "Maxwell", "Maxwell"};

HashMap<String, Integer> duplicates = new HashMap<String, Integer>();
int numberOfDuplicates = 1;

for (int i = 0; i < array.length; i++)
{
    if (duplicates.put(array[i], numberOfDuplicates) != null) // Duplicate Key
    {
        numberOfDuplicates++;
    }
    else // New Key
    {
        numberOfDuplicates = 1;
    }

    duplicates.put(array[i], numberOfDuplicates);
}


// Print out duplicate counts
for (String key : duplicates.keySet()) {
    System.out.println(key + " " + duplicates.get(key));
}

更快的方式/务实的方式呢? 10Q。

【问题讨论】:

  • 你不能比线性时间复杂度更快。
  • @Eran 好的,但是他们有任何内置方法吗?
  • 如果没有损坏,请不要修复它。如果你已经达到了 O(n),就没有理由尝试改进它,而且标准 SDK 没有解决此问题的方法。不过,您的代码可能看起来会更好。
  • 你想在这里达到什么目的?
  • 您总是可以使用多重集,例如来自 Guava,但它基本上是在做同样的事情。

标签: java arrays algorithm duplicates


【解决方案1】:

这里是消除一些杂乱的镜头。

String[] array = {"Henry", "Henry", "Henry", "Maxwell", "Maxwell"};

HashMap<String, Integer> duplicates = new HashMap<String, Integer>();

for (String s : array) {
    Integer i = duplicates.get(s);
    duplicates.put(s, i == null ? 1 : (i+1));
}

【讨论】:

    【解决方案2】:

    您也可以通过以下方式进行操作

            if(duplicates.containsKey(array[i])){
                duplicates.put(array[i],duplicates.get(array[i])+1);
            }else{
                duplicates.put(array[i], 1);
            }
    

    而不是

    if (duplicates.put(array[i], numberOfDuplicates) != null) // Duplicate Key
        {
            numberOfDuplicates++;
        }
        else // New Key
        {
            numberOfDuplicates = 1;
        }
    

    【讨论】:

      【解决方案3】:

      您可以使用 Java 8 Streams 用更少的代码编写它:

      Map<String, Integer> duplicates =
          Arrays.stream(array)
                .collect(Collectors.groupingBy(e -> e, 
                                               Collectors.reducing(0, e -> 1, Integer::sum);
      

      【讨论】:

        【解决方案4】:

        宝藏版

        这是使用 Trove 对 Kayamans 答案的修改,这是一个高性能集合库。

        String[] array = {"Henry", "Henry", "Henry", "Maxwell", "Maxwell"};
        
        TObjectIntMap<String> duplicates = new TObjectIntHashMap<String>();
        for(String s: array) {
           duplicates.adjustOrPutValue(s,1,1);
        }
        
        duplicates.forEachEntry( new TObjectIntProcedure<String>() {
           void execute(String key, int value) {
              System.out.println(key + " " + value);
           };  
        });
        

        就地排序版本

        此版本使用Arrays.sort,然后逐步遍历报告重复的数组。虽然Arrays.sortO(n log n),但生成的算法可能会更快,因为它避免了任何数据结构的分配 - 但它确实改变了输入数组的顺序。

        注意 1: 在这种情况下,时间将由 IO 调用控制,因此您可能不会注意到速度。

        注意 2: 我会重构并提取其核心,并使用仿函数来处理重复项。

        Arrays.sort(array);
        String last = null;
        int count = 0;
        for(String v:array) {
        
            // Is it the first value
            if(last = null) {
               last = v;
               count = 1;
               continue;
            }
        
            // Have we started a new value?
            if(last.equals(v)) {
               System.out.println(last + " " +count);
               last = v;
               count = 1;
               continue;
            }
        
            // Its a repeated value.
            ++count;
        }
        
        if(last!=null)
           System.out.println(last + " " +count);
        

        【讨论】:

          猜你喜欢
          • 2023-03-26
          • 2010-11-20
          • 1970-01-01
          • 2015-12-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-14
          • 2023-04-10
          相关资源
          最近更新 更多