【问题标题】:Finding duplicates in array查找数组中的重复项
【发布时间】:2016-06-23 17:27:12
【问题描述】:

我知道如何在数组中查找重复元素,但最近在一个面试问题中,我被要求在不使用嵌套循环和递归的情况下以单遍含义查找数组中的重复元素。我试过但失败了。面试官连提示都没给我。所以我来这里问,是否可以在没有嵌套循环/递归的情况下找到数组中的重复元素?如果是,任何人都可以提供示例代码吗?也不允许使用库函数

P.S我也想知道如果我们不使用循环或递归会有什么影响。是否与复杂性有关?

【问题讨论】:

  • 我们是否也应该使用 O(1) 额外的内存,或者我们没有这样的限制?
  • 如果允许修改数组,则可以使用排序。
  • @blazs 您不能一次性对数组进行排序。
  • 操作,对。好吧,在我看来,您应该向面试官询问详细信息。你能假设元素是整数吗?如果是,那么您可以使用计数排序进行排序。如果没有,那么您可以使用哈希表并有 O(n) expected 时间。等等等等。
  • 我们不知道面试官到底问了你什么,但正如你的问题所述,这是不可能的。

标签: c arrays duplicates


【解决方案1】:

您可以保留一个哈希表/字典,其中包含每个项目值的项目计数。

【讨论】:

  • @n.m.为什么不允许编写自己的哈希表?
  • @Seb 尝试不使用循环或递归。
  • @n.m.不使用嵌套循环?当然。多个循环可以合并为一个使用continue...
  • @n.m.您刚刚更改了目标...首先您谈论的是“循环和递归”需求,现在您已经转向另一个需求。你意识到你错了第一个吗?没关系,我很高兴继续……您没有足够的信息来推断“在一次遍历中查找数组中的重复元素”到“不得执行其他数组的遍历”。
  • @n.m.这是一个循环,可以精确地访问每个元素一次,是的。这是否意味着每次元素访问都不能循环多次?
【解决方案2】:

由于您没有提及有关数组的任何内容,因此我想说不可能一次性完成。我不确定计数排序是否是您正在寻找的答案。因此,解决问题的唯一方法是使用字典。这是我能在 C 语言中找到的最简单的字典实现。

Quick Way to Implement Dictionary in C

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    因为您想在线性时间内找到重复项,例如一次,您必须使用额外的数据结构来计算每个元素出现的次数。

    这里我假设数组是整数。不过,这适用于任何类型。我使用一个 HashMap,它使用元素(在本例中为整数)作为键,并将出现次数作为值。

    public static ArrayList<Integer> findDuplicates(int[] arr) {
    
       HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
       for (int i = 0; i < arr.length; i++) {
           if (!map.containsKey(arr[i]))
               map.put(arr[i], 1);
           else
               map.put(arr[i], map.get(arr[i]) + 1);
       }
    
       ArrayList<Integer> dups = new ArrayList<Integer>();
    
       for (Integer i : map.keySet())
           if (map.get(i) > 1)
                dups.add(i);
    
      return dups;
    }
    

    所以

    int arr[] = {1,2,3,4,2,1,2,3,4,5,6,7,8};
    findDuplicates(arr);
    

    将返回[1, 2, 3, 4]

    【讨论】:

      【解决方案4】:

      简单但富有创意的解决方案: 提出对数组进行排序的要求 - 然后它就会变得微不足道。 (但这就是面试问题的运作方式)

      【讨论】:

      • 我认为我们可以放心地假设响应是“不错的尝试,但它不是”
      • 我不这么认为——不是我面试的地方。我喜欢听到创造性的答案,而不是教科书上的答案。考虑到虚构的要求,其他答案中提出的哈希是一个完美的解决方案,但不会导致完美的程序。而且,如果您有一个查找重复项的真实案例,那么在请求排序数组时,您可能会大大提高代码质量 - 实际上,这可能是小菜一碟。
      • 我只是认为如果对数组进行排序,它太微不足道了。如果是这样,为什么还要问这个问题?如果给出问题,我可能会用“我假设数组未排序?”来确认它,只是为了让面试官知道我已经想到了,但如果答案是“不,它是排序的,我会非常惊讶,下一个问题”。有什么意义?
      • 重点是:我希望应聘者提出最简单的解决方案。即使它需要讨论并且可能在其他地方重新工作。因为这是我对在我的团队中工作的工程师的期望。考虑到限制,散列是解决问题的一个很好的解决方案,但如果你在一个真正的团队中这样做,你可能不得不被解雇......
      • 如果你在采访聪明的人,而解决方案是“哦,对不起,我忘了告诉你数组已经排序了”,他们可能会觉得这是侮辱。我知道我会的。任何这样的条件都应该是问题陈述的一部分。在真正的问题中,人们不会忽视这一点。
      【解决方案5】:

      我假设整数的大小是 2 个字节。

      #define ARRAY_SIZE 10
      
      int array[ARRAY_SIZE] = {2,3,1,5,1,6,7,7,8,1};
      
      int duplicate[65535] = {0};
      
      for(char i = 0;i< ARRAY_SIZE;i++)
      {
        duplicate[array[i]]++;
        if(duplicate[array[i]] > 1)
        {
           printf(" %d is duplicate in array",array[i]);
        }  
      }
      

      现在,duplicate 数组的每个索引显示一个值在 array 中重复的次数。

      【讨论】:

      • (1) 假设不合理,(2) 这不是 O(n) 解决方案。关于为什么这是错误的另一个错误答案,请参阅我的解释。
      • @TomKarzes 我正在开发 78K0R 编译器,其中 sizeof 整数为 2 个字节。
      • 没关系。这些值可以是双精度数或结构。即使不是,假设您有一个包含 10 个整数的数组,其值范围从 1 到 32767。这几乎不是 O(n) 解决方案,是吗?无论如何,这显然不是 OP 问题的理想答案。
      • @TomKarzes 您能否详细说明为什么这不是 O(n) 解决方案?
      • 因为n是数组的长度,而不是机器可以表示的整数个数。运行时间应与数组的长度成线性关系。如今,大多数现代通用处理器实际上都是 64 位的,但即使是 32 位,创建一个足够大以容纳所有处理器的阵列也是不切实际的。此外,为什么您认为将值限制为非常小的整数是合理的?它也应该适用于双精度或其他数据类型。
      猜你喜欢
      • 2011-12-22
      • 2018-05-16
      • 2013-07-31
      • 1970-01-01
      相关资源
      最近更新 更多