【问题标题】:Algorithm to find duplicate in an array在数组中查找重复项的算法
【发布时间】:2010-11-16 09:34:50
【问题描述】:

我有一个任务是创建一个算法来查找包含数值的数组中的重复项。但它没有说是哪种数字、整数或浮点数。我写了以下伪代码:

 FindingDuplicateAlgorithm(A) // A is the array
      mergeSort(A);
      for  int i <- 0 to i<A.length
           if A[i] == A[i+1]
                 i++
               return  A[i]
           else
                 i++

我是否创建了一个有效的算法? 我认为我的算法有问题,它多次返回重复的数字。例如,如果数组包含两个索引中的 2,我将在输出中包含 ...2, 2,...。如何更改它以仅返回每个重复项一次? 我认为它是一个很好的整数算法,但它也适用于浮点数吗?

【问题讨论】:

  • 小心使用 A[i+1] -- 如果 i = (A.length - 1),会发生坏事。您希望 for 循环仅在 i
  • 对了,谢谢你的指导

标签: algorithm


【解决方案1】:

要处理重复,您可以执行以下操作:

if A[i] == A[i+1]:
    result.append(A[i]) # collect found duplicates in a list
    while A[i] == A[i+1]: # skip the entire range of duplicates 
        i++               # until a new value is found

【讨论】:

  • +1 但是检测重复的浮点并不比检测重复的整数更棘手。当且仅当value1 == value2 时,两个浮点值是相同的。
  • @Andreas:你是对的,但是 equalduplicate 这两个词对于浮点数的含义不同。
  • 不,我不这么认为。一个值a 是另一个值b 的副本当且仅当a == b,没有其他方法可以定义它。
  • mergeSort(Arr); int i
  • @Sandra:我刚刚发布了相关部分。
【解决方案2】:

您想在 Java 中查找重复项吗?

您可以使用 HashSet。

HashSet h = new HashSet();
for(Object a:A){
   boolean b = h.add(a);
   boolean duplicate = !b;
   if(duplicate)
       // do something with a;
}

add() 的返回值定义为:

如果集合还没有,则为真 包含指定的元素。

编辑: 我知道 HashSet 针对插入和包含操作进行了优化。但我不确定它的速度是否足以满足您的担忧。

EDIT2: 我看到你最近添加了作业标签。如果 itf 作业,我不喜欢我的答案,因为它可能是“高级”的算法课

http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashSet.html#add%28java.lang.Object%29

【讨论】:

    【解决方案3】:

    你的答案似乎很不错。第一次排序,他们只是检查相邻值会给你O(n log(n)) 复杂性,这是非常有效的。

    合并排序是O(n log(n)),而检查相邻值只是O(n)

    但有一件事(如其中一个 cmets 所述)您的伪代码将导致堆栈溢出(笑)。内部循环应该是(在 Java 中):

    for (int i = 0; i < array.length - 1; i++) {
        ...
    }
    

    此外,如果您确实想显示哪些数字(和/或索引)是重复项,则需要将它们存储在单独的列表中。

    【讨论】:

      【解决方案4】:

      我不确定你需要用什么语言来编写算法,但是这里有一些非常好的 C++ 解决方案来响应my question。应该对你有用。

      【讨论】:

        【解决方案5】:

        O(n) 算法:遍历数组并尝试将每个元素输入到哈希表/集合中,以数字作为哈希键。如果你不能进入,那就是重复。

        【讨论】:

        • 这似乎与stackoverflow.com/a/4192865 相同。请仅在您有新话要说时才发布答案。如果你这样做,请扩大你的答案。
        • 我的帖子中有两件事不同:提到复杂性以及您必须“尝试”从 .NET 角度插入值的事实。实际上,链接中列出的代码将在 .NET CLR 中为 dups 引发异常,因为它会尝试插入已经存在的密钥。在 .NET 中,您必须在插入之前使用 trygetvalue()。
        【解决方案6】:

        您的算法包含缓冲区溢出。 i 以 0 开头,所以我假设数组 A 的索引是从零开始的,即第一个元素是 A[0],最后一个元素是 A[A.length-1]。现在i 计数到A.length-1,并且在循环体中访问A[i+1],它在最后一次迭代的数组之外。或者,简单地说:如果您将每个元素与下一个元素进行比较,则只能进行长度为 1 的比较。

        如果您只想报告一次重复,我会使用布尔变量firstDuplicate,当您发现重复时设置为 false,当数字与下一个不同时设置为 true。然后,如果firstDuplicate 为真,则仅报告重复的数字,从而仅报告第一个重复。

        【讨论】:

          【解决方案7】:
           public void printDuplicates(int[] inputArray) {
              if (inputArray == null) {
                  throw new IllegalArgumentException("Input array can not be null");
              }
              int length = inputArray.length;
          
              if (length == 1) {
                  System.out.print(inputArray[0] + " ");
                  return;
              }
          
              for (int i = 0; i < length; i++) {
          
                  if (inputArray[Math.abs(inputArray[i])] >= 0) {
                      inputArray[Math.abs(inputArray[i])] = -inputArray[Math.abs(inputArray[i])];
                  } else {
                      System.out.print(Math.abs(inputArray[i]) + " ");
                  }
              }
          }
          

          【讨论】:

          • 请解释你的答案。 SO 的存在是为了教育人们,而不仅仅是回答问题
          • 当然。这里的主要思想 - 是使用数组中的数字作为索引。第 1 步 - 在索引 inputArray[i] 下的所有数字的循环更改符号。第 0 步 - 检查数字是否为负数。如果是 - 那么当前元素上还有另一个数字,并且已经改变了它
          • @smaiakov,如果数组元素本身大于数组大小怎么办?我们会跳出边界异常。
          猜你喜欢
          • 2022-07-16
          • 2015-12-01
          • 2018-05-16
          • 1970-01-01
          相关资源
          最近更新 更多