【问题标题】:How can we find a repeated number in array in O(n) time and O(1) space complexity我们如何在 O(n) 时间和 O(1) 空间复杂度内找到数组中的重复数字
【发布时间】:2011-09-10 10:02:44
【问题描述】:

我们如何在 O(n) 时间和 O(1) 复杂度内找到数组中的重复数字? 例如 数组 2,1,4,3,3,10 输出为 3

编辑: 我尝试了以下方式。 我发现如果 no 奇怪地重复,那么我们可以通过执行 xor 来实现结果。所以我想使奇数的元素不重复甚至不重复,并且每个均匀重复的不重复。但是为此,我需要从 O(n) 中的输入数组中找出唯一的元素数组,但找不到方法。

【问题讨论】:

  • 空间复杂度为 O(1) 我不知道你为什么有 data-structures 标签。

标签: algorithm data-structures


【解决方案1】:

假设数组中的数字值有一个上限(我曾经使用过的所有编程语言中的所有内置整数类型都是这种情况——例如,假设它们是 32 -bit 整数)有一个使用常量空间的解决方案:

  1. 创建一个包含 N 个元素的数组,其中 N 是输入数组中整数值的上限,并将所有元素初始化为 0false 或类似的值。我将其称为 lookup 数组。
  2. 循环输入数组,并使用每个数字来索引查找数组。如果您找到的值为1true(等),则输入数组中的当前数字是重复的。
  3. 否则,将查找数组中的对应值设置为1true,以记住我们已经看到了这个特定的输入数字。

技术上,这是 O(n) 时间和 O(1) 空间,它不会破坏输入数组。实际上,您需要按自己的方式运行这样的程序才能真正运行(例如,如果在输入中谈论 64 位整数是不可能的)。

【讨论】:

  • 是的,我也想到了那个解决方案,但复杂度是 O(K*n),其中 k 不是比特数。如果 k>logn,那么 O(nlogn) 将是有效的解决方案。
  • 这个解决方案在空间中的 O(1) 怎么样?如果我们有 0,1,2,3... 2^32-1,2^32-1 作为输入,则需要一个大小为 2^32 位的数组,大小等于 = 2^27 个整数.这肯定不是 O(1)。
  • @NitinGarg:你对 O(1) 的定义是错误的。这个解决方案需要一个大小为2^32的数组不管输入是什么,因此它是O(1)。
  • @Jon - 通过同样的技术,您可以迭代数组 2^32 次,每次迭代都会查找单个数字的重复项(仅使用布尔值来存储我是否找到了一个,并且如果我找到另一个,那么我有一个副本)。从技术上讲,它是 O(n),当然也是 O(1) 空间。
  • @Jon - 对于整数排序,我可以创建一个包含 2^32 个元素的数组 X,所有元素都初始化为 0。现在我遍历整数的原始序列 (a1,a2...ai. .. a) 并在每一步将 X[ai] 加 1。最后,我只需要在 X 上进行一个循环,花费 n + 2^32(恒定时间)来获得排序后的序列。
【解决方案2】:

如果不了解数组中可能的值的更多信息,您将无法做到。

对于 O(1) 空间要求,最快的方法是对数组进行排序,使其至少为 O(n*log(n))。

【讨论】:

    【解决方案3】:

    使用位操作...在一个循环中遍历列表。

    1. 通过移动 i 的值来检查掩码是否为 1。
    2. 如果是这样,打印出重复值 i。
    3. 如果未设置该值,请设置它。

    *如果您只想显示一个重复值一次,请添加另一个整数显示并设置其位,如下例所示。

    **这是在 java 中,我不确定我们是否会达到它,但您可能还想使用 Integer.MAX_VALUE 添加检查。

        public static void repeated( int[] vals ) {
            int mask = 0;
            int show = 0;
            for( int i : vals ) {
                // get bit in mask
                if( (( mask >> i ) & 1) == 1 &&
                    (( show >> i ) & 1) == 0 )
                {
                    System.out.println( "\n\tfound: " + i );
                    show = show | (1 << i);
                }
    
                // set mask if not found
                else
                {
                    mask = mask | (1 << i);
                    System.out.println( "new: " + i );
                }
    
                System.out.println( "mask: " + mask );
            }
        }
    

    【讨论】:

    • 别忘了这个逻辑只有在你有一种类型的值时才有效,要么都是正的,要么是负的。对于 (-17, 15) 等值,上述操作将失败
    【解决方案4】:

    如果不知道有关输入数组的任何限制规则,这是不可能的,要么内存复杂度会依赖于输入大小,要么时间复杂度会更高。

    上面的 2 个答案实际上是接近您所要求的最佳答案,一个权衡是时间,第二个权衡是在内存中,但您不能让它在 O(n) 时间和 O(1 ) 某些未知输入数组中的复杂性。

    【讨论】:

      【解决方案5】:

      我也遇到了这个问题,我的解决方案是使用 hashMap 。python 版本如下:

        def findRepeatNumber(lists):
            hashMap = {}
            for i in xrange(len(lists)):
                if lists[i] in hashMap:
                    return lists[i]
                else: 
                    hashMap[lists[i]]=i+1
            return
      

      【讨论】:

      • 他想要一个 o(1) 空间。你的空间是 o(n) ;)
      【解决方案6】:

      只有当你有特定的数据时才有可能。例如,所有数字的范围都很小。然后您可以将重复信息存储在源数组中,而不影响整个扫描和分析过程。

      简化示例:您知道所有数字都小于 100,然后您可以使用额外的零标记数字的重复计数,例如当 9 出现两次时将 900 代替 9。

      当 NumMax-NumMin 时很容易

      http://www.geeksforgeeks.org/find-the-maximum-repeating-number-in-ok-time/

      【讨论】:

        【解决方案7】:
        public static string RepeatedNumber()
            {
                int[] input = {66, 23, 34, 0, 5, 4};
                int[] indexer = {0,0,0,0,0,0}
                var found = 0;
                for (int i = 0; i < input.Length; i++)
                {
                    var toFind = input[i];
                    for (int j = 0; j < input.Length; j++)
                    {
                        if (input[j] == toFind && (indexer[j] == 1))
                        {
                            found = input[j];
                        }
                        else if (input[j] == toFind)
                        {
                            indexer[j] = 1;
                        }
                    }
        
                }
        
        
            return $"most repeated item in the array is {found}";
        

        }

        【讨论】:

        • O(n^2) 时间
        【解决方案8】:

        你可以这样做

        #include<iostream.h>
        #include<conio.h>
        #include<stdio.h>
        void main ()
        {
            clrscr();
            int array[5],rep=0;
            for(int i=1; i<=5; i++)
            {
                cout<<"enter elements"<<endl;
                cin>>array[i];
            }
            for(i=1; i<=5; i++)
            {
                if(array[i]==array[i+1])
                {
                    rep=array[i];
                }
            }
            cout<<" repeat value is"<<rep;
            getch();
        }
        

        【讨论】:

        • 你确定你得到答案了吗?如果重复的数字不在一起怎么办?
        猜你喜欢
        • 1970-01-01
        • 2015-05-25
        • 2012-08-06
        • 1970-01-01
        • 2016-06-21
        • 2011-08-09
        • 1970-01-01
        • 2012-01-02
        • 1970-01-01
        相关资源
        最近更新 更多