【问题标题】:Quickest way to find missing number in an array of numbers在数字数组中查找缺失数字的最快方法
【发布时间】:2011-01-07 23:59:22
【问题描述】:

我有一个从 1 到 100(包括两者)的数字数组。数组的大小为 100。数字是随机添加到数组中的,但数组中有一个随机的空槽。 找到该插槽以及应该放入插槽的数字的最快方法是什么?最好使用 Java 解决方案。

【问题讨论】:

  • 其实我知道一个解决方案 - 找到从 1 到 100 的数字之和,然后从数组中的数字之和中减去它以获得丢失的数字。我很想看看是否可以任何其他有趣的解决方案。
  • 'empty' 的值是多少? 0? -1?
  • 我在一次采访中被问到这个问题
  • 我认为sayro的答案在这种情况下是最好的
  • 如果你的整数不是从 1 开始,这怎么办?例如 { 15, 16, 17, 19, 20} ?

标签: java arrays algorithm


【解决方案1】:

另一个家庭作业问题。顺序搜索是您能做的最好的事情。至于 Java 解决方案,请考虑为读者练习。 :P

【讨论】:

    【解决方案2】:

    你可以在 O(n) 中做到这一点。遍历数组并计算所有数字的总和。现在,从 1 到 N 的自然数之和可以表示为Nx(N+1)/2。在您的情况下,N=100。

    Nx(N+1)/2 中减去数组的总和,其中 N=100。

    那是缺少的数字。在计算总和的迭代过程中可以检测到空槽。

    // will be the sum of the numbers in the array.
    int sum = 0;
    int idx = -1;
    for (int i = 0; i < arr.length; i++)
    {
        if (arr[i] == 0)
        {
             idx = i; 
        }
        else 
        {
             sum += arr[i];
        }
    }
    
    // the total sum of numbers between 1 and arr.length.
    int total = (arr.length + 1) * arr.length / 2;
    
    System.out.println("missing number is: " + (total - sum) + " at index " + idx);
    

    【讨论】:

    • 您可以在第一次迭代时记下任何索引为零。
    • 求和是整数溢出的质数,下面的方法应该注意这一点:对所有给定的数字进行异或,调用这个 X1 XOR 从 1 到 100 的所有数字,调用这个 X2 X1 XOR X2 应该是缺少数字,因为所有重复的数字都异或了。
    • @AbhinavSharma 是的,但如果发生溢出,它也适用于求和,前提是溢出很好地包装,这在 Java 和 C 中对于无符号类型都有保证。
    • 在这种情况下,total 应该是 (arr.length + 1) * (arr.length + 2) / 2 以满足 n * (n + 1) /2 因为对于大多数语言来说,数组索引从 0 开始,我们需要将长度增加 1
    • 对于此扫描仪,请考虑缺少 2 个数字。您的解决方案是什么?
    【解决方案3】:

    (1到n的总和)-(数组中所有值的总和)=缺失的数字

    int sum = 0;
    int idx = -1;
    for (int i = 0; i < arr.length; i++) {
      if (arr[i] == 0) idx = i; else sum += arr[i];
    }
    System.out.println("missing number is: " + (5050 - sum) + " at index " + idx);
    

    【讨论】:

    • 什么是 5050?鉴于包含 1,2,0,4,5 的数组,此代码似乎不起作用。
    • @core_pro 您的示例数组的大小是 5,而不是 OP 指定的 100。 5050 是从 1 到 100 的所有整数的总和,适用于具有 100 个元素的数组。因此,对于大小为 5 的数组,等效值为 15。
    【解决方案4】:

    快速排序是效率最高的最佳选择......

    【讨论】:

    • 实际上,如果你使用快速排序,你会得到 O(n log n)。用你的大脑执行一个真正的算法会给你 O(n)
    【解决方案5】:

    这是 c#,但它应该非常接近您的需要:

    int sumNumbers = 0;
    int emptySlotIndex = -1;
    
    for (int i = 0; i < arr.length; i++)
    {
      if (arr[i] == 0)
        emptySlotIndex = i;
      sumNumbers += arr[i];
    }
    
    int missingNumber = 5050 - sumNumbers;
    

    【讨论】:

      【解决方案6】:

      我认为最简单且可能最有效的解决方案是遍历所有条目并使用 bitset 来记住设置了哪些数字,然后测试 0 位。位为 0 的条目是缺失的数字。

      【讨论】:

        【解决方案7】:
            //Array is shorted and if writing in C/C++ think of XOR implementations in java as follows.
                            int num=-1;
            for (int i=1; i<=100; i++){
                num =2*i;
                if(arr[num]==0){
                 System.out.println("index: "+i+" Array position: "+ num);      
                 break;
                }
                else if(arr[num-1]==0){
                 System.out.println("index: "+i+ " Array position: "+ (num-1)); 
                 break;             
                }           
            }// use Rabbit and tortoise race, move the dangling index faster, 
             //learnt from Alogithimica, Ameerpet, hyderbad**
        

        【讨论】:

          【解决方案8】:

          例如,不涉及重复添加或 n(n+1)/2 公式的解决方案不会在面试时找到您。

          您必须使用 4 个整数(32 位)或 2 个整数(64 位)的数组。用 (-1 & ~(1 > 3 初始化最后一个 int。(大于 100 的位设置为 1)或者您可以使用 for 循环设置大于 100 的位。

          1. 遍历数字数组并将与数字对应的位位置设置为 1(例如,71 将设置在从左到右第 7 位的第 3 个 int 上)
          2. 遍历 4 个整数(32 位版本)或 2 个整数(64 位版本)的数组
          public int MissingNumber(int a[]) { int bits = sizeof(int) * 8; int i = 0; int no = 0; while(a[i] == -1)//this means a[i]'s bits are all set to 1, the numbers is not inside this 32 numbers section { no += bits; i++; } return no + bits - Math.Log(~a[i], 2);//apply NOT (~) operator to a[i] to invert all bits, and get a number with only one bit set (2 at the power of something) }

          示例:(32 位版本)假设缺少的数字是 58。这意味着第二个整数的第 26 位(从左到右)设置为 0。

          第一个 int 是 -1(所有位都已设置)所以,我们继续进行第二个并将数字 32 添加到“no”。第二个 int 与 -1 不同(未设置位)所以,通过将 NOT (~) 运算符应用于我们得到 64 的数字。可能的数字是 2 的 x 次方,我们可以使用以 2 为底的 log 来计算 x;在这种情况下,我们得到 log2(64) = 6 => 32 + 32 - 6 = 58。

          希望这会有所帮助。

          【讨论】:

            【解决方案9】:

            如果数组是随机填充的,那么您最多可以进行 O(n) 复杂度的线性搜索。但是,我们可以通过类似于 giri 指出的快速排序的分而治之方法将复杂性提高到 O(log n),因为这些数字是按升序/降序排列的。

            【讨论】:

            • 这没有回答如何找出丢失的数字。
            【解决方案10】:

            这个程序会找到丢失的数字

            <?php
            $arr_num=array("1","2","3","5","6");
            $n=count($arr_num);
            for($i=1;$i<=$n;$i++)
            {       
                  if(!in_array($i,$arr_num))
                  {
                  array_push($arr_num,$i);print_r($arr_num);exit;
                  }
            
            }
            ?>
            

            【讨论】:

            • 这个答案应该在 PHP 下归档。该问题在 JAVA 下提交。然而它可以留在这里,因为真正的算法总是与语法无关:)
            【解决方案11】:

            这是一个亚马逊面试问题,最初在这里回答:We have numbers from 1 to 52 that are put into a 51 number array, what's the best way to find out which number is missing?

            回答如下:

            1) Calculate the sum of all numbers stored in the array of size 51. 
            2) Subtract the sum from (52 * 53)/2 ---- Formula : n * (n + 1) / 2.
            

            这里也有博客:Software Job - Interview Question

            【讨论】:

            • 我用 1,2,3 和 5 作为序列进行了尝试。 (即 4 是缺失的数字)。值的总和是 11,所以我做了 ((11*12)/2)-11,我得到了 55。为什么我没有得到 4?
            • n 是数字的个数。所以,它应该是 5*(5+1)/2 = 15...和 ​​15 - (1+2+3+5) = 4。
            • n 是数字的个数。所以,它应该是 4(1,2,3 & 5)。你是怎么得到 5 的,是这个数字的最大值。
            • @mparnisari 是的,这就是我在这里发帖的原因,因为我认为原始帖子(我发布在我的博客上)没有得到任何信用(参考)。它发生在我身上好几次,有些人只是复制代码并完全按照原样发布(就像在我的博客上一样),甚至不参考原始帖子。顺便说一句,感谢您的负分/减分!
            • @SidD n 是系列 1…N 中的最大数
            【解决方案12】:

            好吧,使用布隆过滤器。

            int findmissing(int arr[], int n)
            {
                long bloom=0;
                int i;
                for(i=0; i<;n; i++)bloom+=1>>arr[i];
                for(i=1; i<=n, (bloom<<i & 1); i++);
                return i;
            }
            

            【讨论】:

              【解决方案13】:

              让给定的数组是长度为 N 的 A。假设在给定的数组中,单个空槽被 0 填充。

              我们可以使用许多方法找到这个问题的解决方案,包括Counting sort 中使用的算法。但是,就有效的时间和空间使用而言,我们有两种算法。一种主要使用加法、减法和乘法。另一个使用 XOR。从数学上讲,这两种方法都可以正常工作。但在编程上,我们需要使用主要措施评估所有算法,例如

              • 限制(如输入值很大 (A[1...N]) 和/或 输入值很大(N))
              • 涉及的条件检查次数
              • 涉及的数学运算的数量和类型

              等等。这是因为时间和/或硬件(硬件资源限制)和/或软件(操作系统限制,编程语言限制等)等方面的限制。让我们列出并评估它们各自的优缺点。

              算法一:

              在算法 1 中,我们有 3 个实现。

              1. 使用数学公式(1+2+3+...+N=(N(N+1))/2)计算所有数字的总和(包括未知的缺失数字)。在这里,N=100。计算所有给定数字的总和。从第一个结果中减去第二个结果将得到缺失的数字。

                Missing Number = (N(N+1))/2) - (A[1]+A[2]+...+A[100])

              2. 使用数学公式(1+2+3+...+N=(N(N+1))/2)计算所有数字的总和(包括未知的缺失数字)。在这里,N=100。从该结果中,减去每个给定的数字会得到缺失的数字。

                Missing Number = (N(N+1))/2)-A[1]-A[2]-...-A[100]

                (Note:虽然第二个实现的公式是从第一个派生的,但从数学的角度来看,两者是相同的。但从编程的角度来看,两者是不同的,因为第一个公式比第二个更容易发生位溢出一个(如果给定的数字足够大)。即使加法比减法快,第二种实现减少了由大值相加引起的位溢出的机会(它没有完全消除,因为仍然存在很小的机会,因为(@ 987654331@) 在公式中)。但是两者都同样容易通过乘法发生位溢出。限制是两个实现只有在N(N+1)&lt;=MAXIMUM_NUMBER_VALUE 时才能给出正确的结果。对于第一个实现,额外的限制是它只有在以下情况下才能给出正确的结果Sum of all given numbers&lt;=MAXIMUM_NUMBER_VALUE.)

              3. 计算所有数字的总和(包括未知的缺失数字)并在同一循环中并行减去每个给定数字。这消除了乘法位溢出的风险,但加减法容易发生位溢出。

                //ALGORITHM missingNumber = 0; foreach(index from 1 to N) { missingNumber = missingNumber + index; //Since, the empty slot is filled with 0, //this extra condition which is executed for N times is not required. //But for the sake of understanding of algorithm purpose lets put it. if (inputArray[index] != 0) missingNumber = missingNumber - inputArray[index]; }

              在编程语言(如 C、C++、Java 等)中,如果表示整数数据类型的位数是有限的,那么上述所有实现都容易因为求和、减法和乘法而发生位溢出,导致在输入值较大(A[1...N])和/或输入值较大(N)的情况下会出现错误结果。

              算法二:

              我们可以使用异或的性质来解决这个问题,而不用担心位溢出的问题。而且 XOR 比求和更安全、更快。我们知道异或的性质,即两个相同数的异或等于 0(A XOR A = 0)。如果我们计算从 1 到 N 的所有数字的 XOR(这包括未知的缺失数字),然后根据这个结果,对所有给定的数字进行 XOR,共同的数字被抵消(因为A XOR A=0)最后我们得到丢失的号码。如果我们没有位溢出问题,我们可以使用求和和基于 XOR 的算法来获得解决方案。但是,使用异或的算法比使用加法、减法和乘法的算法更安全、更快。并且可以避免加减乘法带来的额外烦恼。

              在算法1的所有实现中,我们都可以使用异或来代替加减法。

              假设,XOR(1...N) = XOR of all numbers from 1 to N

              实施 1 => Missing Number = XOR(1...N) XOR (A[1] XOR A[2] XOR...XOR A[100])

              实施 2 => Missing Number = XOR(1...N) XOR A[1] XOR A[2] XOR...XOR A[100]

              实施 3 =>

              //ALGORITHM
              missingNumber = 0;
              foreach(index from 1 to N)
              {
                  missingNumber = missingNumber XOR index;
                  //Since, the empty slot is filled with 0,
                  //this extra condition which is executed for N times is not required.
                  //But for the sake of understanding of algorithm purpose lets put it.
                  if (inputArray[index] != 0)
                      missingNumber = missingNumber XOR inputArray[index];
              }
              

              算法 2 的所有三个实现都可以正常工作(从编程的角度来看也是如此)。一种优化是,类似于

              1+2+....+N = (N(N+1))/2
              

              我们有,

              1 XOR 2 XOR .... XOR N = {N if REMAINDER(N/4)=0, 1 if REMAINDER(N/4)=1, N+1 if REMAINDER(N/4)=2, 0 if REMAINDER(N/4)=3}
              

              我们可以通过数学归纳法证明这一点。因此,我们可以使用这个公式来减少 XOR 操作的次数,而不是通过 XOR 来计算 XOR(1...N) 的值。

              此外,使用上述公式计算 XOR(1...N) 有两种实现方式。实施明智,计算

              // Thanks to https://a3nm.net/blog/xor.html for this implementation
              xor = (n>>1)&1 ^ (((n&1)>0)?1:n)
              

              比计算快

              xor = (n % 4 == 0) ? n : (n % 4 == 1) ? 1 : (n % 4 == 2) ? n + 1 : 0;
              

              所以,优化后的 Java 代码是,

              long n = 100;
              long a[] = new long[n];
              
              //XOR of all numbers from 1 to n
              // n%4 == 0 ---> n
              // n%4 == 1 ---> 1
              // n%4 == 2 ---> n + 1
              // n%4 == 3 ---> 0
              
              //Slower way of implementing the formula
              // long xor = (n % 4 == 0) ? n : (n % 4 == 1) ? 1 : (n % 4 == 2) ? n + 1 : 0;
              //Faster way of implementing the formula
              // long xor = (n>>1)&1 ^ (((n&1)>0)?1:n);
              long xor = (n>>1)&1 ^ (((n&1)>0)?1:n);
              
              for (long i = 0; i < n; i++)
              {
                  xor = xor ^ a[i];
              }
              //Missing number
              System.out.println(xor);
              

              【讨论】:

              • 这个答案看起来很有趣,但需要更多解释。
              • 数字与自身的异或为零。因此,如果我们将数组中的所有数字与从 1 到 n 的所有数字进行异或,我们将只剩下缺失的数字
              • 拜托,谁能解释一下为什么初始值需要以 4 为模?
              • @jschank:这是计算总和时的 n(n+1) / 2 的类似物。您可以通过归纳证明1 xor 2 xor ... xor nn1n + 10,具体取决于n % 4
              • 这是最好的答案。
              【解决方案14】:

              您可以做的一件事是使用快速排序对数字进行排序。然后使用for循环从1到100遍历排序后的数组。在每次迭代中,将数组中的数字与for循环增量进行比较,如果发现索引增量与数组值不同,则找到了您丢失的号码以及丢失的索引。

              【讨论】:

                【解决方案15】:

                现在我对大 O 表示法太敏感了,但你不能也做一些类似(在 Java 中)的事情

                for (int i = 0; i < numbers.length; i++) {
                    if(numbers[i] != i+1){
                        System.out.println(i+1);
                    }
                }
                

                其中 numbers 是您的数字从 1 到 100 的数组。 根据我对问题的阅读,它没有说明何时写出丢失的数字。

                或者,如果您可以将 i+1 的值放入另一个数组并在迭代后将其打印出来。

                当然它可能不遵守时空规则。就像我说的。我必须对 Big O 进行强力复习。

                【讨论】:

                • OP说数组中的数字可以不排序
                • 输入 (0,1) 将失败
                【解决方案16】:

                这是一个在整数数组中查找缺失数字的简单程序

                ArrayList<Integer> arr = new ArrayList<Integer>();
                int a[] = { 1,3,4,5,6,7,10 };
                int j = a[0];
                for (int i=0;i<a.length;i++)
                {
                    if (j==a[i])
                    {
                        j++;
                        continue;
                    }
                    else
                    {
                        arr.add(j);
                        i--;
                    j++;
                    }
                }
                System.out.println("missing numbers are ");
                for(int r : arr)
                {
                    System.out.println(" " + r);
                }
                

                【讨论】:

                • 我检查了这里写的每一个函数,这是唯一有效的!谢谢。
                • 正如@MladenOršolić 指出的那样,如果数组中的数字未按排序顺序排列,那么您的解决方案将不起作用。因此,为了使用您的解决方案排序数组是先决条件
                • 这是一个不错的解决方案。
                【解决方案17】:

                我们可以使用比求和更安全的异或运算,因为在编程语言中,如果给定的输入很大,它可能会溢出并给出错误的答案。

                在找到解决方案之前,请了解A xor A = 0。因此,如果我们对两个相同的数字进行异或运算,则值为 0。

                现在,与数组中存在的元素进行异或 [1..n] 会取消相同的数字。所以最后我们会得到缺失的数字。

                // Assuming that the array contains 99 distinct integers between 1..99
                // and empty slot value is zero
                int XOR = 0;
                for(int i=0; i<100; i++) {
                    if (ARRAY[i] != 0) // remove this condition keeping the body if no zero slot
                        XOR ^= ARRAY[i];
                    XOR ^= (i + 1);
                }
                return XOR;
                //return XOR ^ ARRAY.length + 1; if your array doesn't have empty zero slot. 
                

                【讨论】:

                • 独特的解决方案。我也喜欢它处理潜在溢出情况的方式。
                • 什么是异或初始值?
                • @Dejell 它应该是零。
                • 只有当所有元素都在数组中排序时,这个带有 XOR 的解决方案才有效。但是在给定的问题中,元素是随机顺序的。这个解决方案不起作用。
                • 您的答案不适用于以下输入 int arr1[] = {1,3,4,5};整数异或 = 0; for(int i=0; i
                【解决方案18】:

                以下是从给定数组中查找所有缺失数字的解决方案:

                public class FindMissingNumbers {
                
                /**
                 * The function prints all the missing numbers from "n" consecutive numbers.
                 * The number of missing numbers is not given and all the numbers in the
                 * given array are assumed to be unique.
                 * 
                 * A similar approach can be used to find all no-unique/ unique numbers from
                 * the given array
                 * 
                 * @param n
                 *            total count of numbers in the sequence
                 * @param numbers
                 *            is an unsorted array of all the numbers from 1 - n with some
                 *            numbers missing.
                 * 
                 */
                public static void findMissingNumbers(int n, int[] numbers) {
                
                    if (n < 1) {
                        return;
                    }
                
                    byte[] bytes = new byte[n / 8];
                    int countOfMissingNumbers = n - numbers.length;
                
                    if (countOfMissingNumbers == 0) {
                        return;
                    }
                
                    for (int currentNumber : numbers) {
                
                        int byteIndex = (currentNumber - 1) / 8;
                        int bit = (currentNumber - byteIndex * 8) - 1;
                        // Update the "bit" in bytes[byteIndex]
                        int mask = 1 << bit;
                        bytes[byteIndex] |= mask;
                    }
                    for (int index = 0; index < bytes.length - 2; index++) {
                        if (bytes[index] != -128) {
                            for (int i = 0; i < 8; i++) {
                                if ((bytes[index] >> i & 1) == 0) {
                                    System.out.println("Missing number: " + ((index * 8) + i + 1));
                                }
                            }
                        }
                    }
                    // Last byte
                    int loopTill = n % 8 == 0 ? 8 : n % 8;
                    for (int index = 0; index < loopTill; index++) {
                        if ((bytes[bytes.length - 1] >> index & 1) == 0) {
                            System.out.println("Missing number: " + (((bytes.length - 1) * 8) + index + 1));
                        }
                    }
                
                }
                
                public static void main(String[] args) {
                
                    List<Integer> arrayList = new ArrayList<Integer>();
                    int n = 128;
                    int m = 5;
                    for (int i = 1; i <= n; i++) {
                        arrayList.add(i);
                    }
                    Collections.shuffle(arrayList);
                    for (int i = 1; i <= 5; i++) {
                        System.out.println("Removing:" + arrayList.remove(i));
                    }
                    int[] array = new int[n - m];
                    for (int i = 0; i < (n - m); i++) {
                        array[i] = arrayList.get(i);
                    }
                    System.out.println("Array is: " + Arrays.toString(array));
                
                    findMissingNumbers(n, array);
                }
                
                }
                

                【讨论】:

                  【解决方案19】:

                  假设您的 n 为 8,对于此示例,我们的数字范围为 0-8 我们可以如下表示所有 9 个数字的二进制表示 0000 0001 0010 0011 0100 0101 0110 0111 1000

                  在上面的序列中,没有丢失的数字,并且在每一列中,0 和 1 的数量匹配,但是,一旦您删除 1 个值,比如说 3,我们就会在各列中的 0 和 1 的数量上保持平衡.如果一列中 0 的数量 在该位的位置 1 的数量,则该位的位置将为 1 . 我们从左到右测试位,并且在每次迭代中,我们丢弃数组的一半以测试下一位,奇数数组值或偶数数组值在每次迭代时被丢弃,具体取决于我们缺少哪个位在。

                  下面的解决方案是用 C++ 编写的

                  int getMissingNumber(vector<int>* input, int bitPos, const int startRange)
                  {
                      vector<int> zeros;
                      vector<int> ones;
                      int missingNumber=0;
                  
                      //base case, assume empty array indicating start value of range is missing
                      if(input->size() == 0)
                          return startRange;
                  
                      //if the bit position being tested is 0 add to the zero's vector
                      //otherwise to the ones vector
                      for(unsigned int i = 0; i<input->size(); i++)
                      {
                          int value = input->at(i);
                          if(getBit(value, bitPos) == 0)
                              zeros.push_back(value);
                          else
                              ones.push_back(value);
                      }
                  
                      //throw away either the odd or even numbers and test
                      //the next bit position, build the missing number
                      //from right to left
                      if(zeros.size() <= ones.size())
                      {
                          //missing number is even
                          missingNumber = getMissingNumber(&zeros, bitPos+1, startRange);
                          missingNumber = (missingNumber << 1) | 0;
                      }
                      else
                      {
                          //missing number is odd
                          missingNumber = getMissingNumber(&ones, bitPos+1, startRange);
                          missingNumber = (missingNumber << 1) | 1;
                      }
                  
                      return missingNumber;
                  }
                  

                  在每次迭代中,我们将输入空间减少 2,即 N, N/2,N/4 ... = O(log N),空间为 O(N)

                  //Test cases 
                  [1] when missing number is range start
                  [2] when missing number is range end
                  [3] when missing number is odd
                  [4] when missing number is even
                  

                  【讨论】:

                    【解决方案20】:

                    这不是搜索问题。雇主想知道您是否掌握了校验和。如果您正在寻找多个唯一整数,您可能需要一个二进制或 for 循环或其他任何东西,但问题规定“一个随机的空槽”。在这种情况下,我们可以使用流求和。条件:“数字随机添加到数组中”没有更多细节是没有意义的。该问题不假定数组必须以整数 1 开头,因此可以容忍偏移起始整数。

                    int[] test = {2,3,4,5,6,7,8,9,10,  12,13,14 };
                    
                    /*get the missing integer*/
                    
                    int max = test[test.length - 1];
                    int min = test[0];
                    int sum = Arrays.stream(test).sum();
                    int actual = (((max*(max+1))/2)-min+1);
                    //Find:
                    
                    //the missing value
                    System.out.println(actual - sum);
                    //the slot
                    System.out.println(actual - sum - min);
                    

                    成功时间:0.18 内存:320576 信号:0

                    【讨论】:

                    • 毫无疑问! Stream 在 8 中很有用,特别是在这种情况下,用更少的行来总结建议的解决方案的概念。如果 Java 7 及更低版本喜欢创建 int sum,则可以使用 for 循环。
                    【解决方案21】:

                    在类似的场景中,数组已经排序,它不包含重复项,并且只有一个数字丢失,可以在 log(n) 中找到这个丢失的数字时间,使用二分查找。

                    public static int getMissingInt(int[] intArray, int left, int right) {
                        if (right == left + 1) return intArray[right] - 1;
                        int pivot = left + (right - left) / 2;
                        if (intArray[pivot] == intArray[left] + (intArray[right] - intArray[left]) / 2 - (right - left) % 2)
                            return getMissingInt(intArray, pivot, right);
                        else 
                            return getMissingInt(intArray, left, pivot);
                    }
                    
                    public static void main(String args[]) {
                        int[] array = new int[]{3, 4, 5, 6, 7, 8, 10};
                        int missingInt = getMissingInt(array, 0, array.length-1);
                        System.out.println(missingInt); //it prints 9
                    }
                    

                    【讨论】:

                    • 好,你能解释一下为什么我们需要 [- (right - left) % 2 ]
                    • 我同意,这是我见过的此类算法的最佳解决方案之一。出于好奇,我还想解释一下(右-左)% 2。
                    【解决方案22】:

                    用 PHP 解决 $n = 100;

                    $n*($n+1)/2 - array_sum($array) = $missing_number
                    

                    array_search($missing_number)会给出缺失号码的索引

                    【讨论】:

                    • 这个find that [empty] slot怎么样?
                    【解决方案23】:

                    我在这里找到了这个漂亮的解决方案:

                    http://javaconceptoftheday.com/java-puzzle-interview-program-find-missing-number-in-an-array/

                    public class MissingNumberInArray
                    {
                        //Method to calculate sum of 'n' numbers
                    
                        static int sumOfNnumbers(int n)
                        {
                            int sum = (n * (n+1))/ 2;
                    
                            return sum;
                        }
                    
                        //Method to calculate sum of all elements of array
                    
                        static int sumOfElements(int[] array)
                        {
                            int sum = 0;
                    
                            for (int i = 0; i < array.length; i++)
                            {
                                sum = sum + array[i];
                            }
                    
                            return sum;
                        }
                    
                        public static void main(String[] args)
                        {
                            int n = 8;
                    
                            int[] a = {1, 4, 5, 3, 7, 8, 6};
                    
                            //Step 1
                    
                            int sumOfNnumbers = sumOfNnumbers(n);
                    
                            //Step 2
                    
                            int sumOfElements = sumOfElements(a);
                    
                            //Step 3
                    
                            int missingNumber = sumOfNnumbers - sumOfElements;
                    
                            System.out.println("Missing Number is = "+missingNumber);
                        }
                    }
                    

                    【讨论】:

                    • 虽然这与接受的答案共享int 的总数的可疑用途,但它与它有何不同,它增加了什么?
                    • 这是我一直在寻找的最简单的逻辑答案!谢谢你:)
                    • 很高兴它帮助了你 Shekhar :)
                    【解决方案24】:
                    function solution($A) {
                        // code in PHP5.5
                        $n=count($A);
                        for($i=1;$i<=$n;$i++) {
                           if(!in_array($i,$A)) {
                                  return (int)$i;
                           }
                        }
                    }
                    

                    【讨论】:

                    • 请考虑在解释中进行编辑 - 没有它,您的答案会被评论者标记为低质量。
                    【解决方案25】:

                    ========排序数组的最简单解决方案===========

                    public int getMissingNumber(int[] sortedArray)
                            {
                                int missingNumber = 0;
                                int missingNumberIndex=0;
                                for (int i = 0; i < sortedArray.length; i++)
                                {
                                    if (sortedArray[i] == 0)
                                    {
                                        missingNumber = (sortedArray[i + 1]) - 1;
                                        missingNumberIndex=i;
                                        System.out.println("missingNumberIndex: "+missingNumberIndex);
                                        break;
                                    }
                                }
                                return missingNumber;
                            }
                    

                    【讨论】:

                      【解决方案26】:

                      从一系列数字中找到缺失的数字。要记住的 IMP 点。

                      1. 应该对数组进行排序..
                      2. 该函数不适用于多个缺失。
                      3. 序列必须是 AP。

                            public int execute2(int[] array) {
                            int diff = Math.min(array[1]-array[0], array[2]-array[1]);
                            int min = 0, max = arr.length-1;
                            boolean missingNum = true;
                            while(min<max) {
                                int mid = (min + max) >>> 1;
                                int leftDiff = array[mid] - array[min];
                                if(leftDiff > diff * (mid - min)) {
                                    if(mid-min == 1)
                                        return (array[mid] + array[min])/2;
                                    max = mid;
                                    missingNum = false;
                                    continue;
                                }
                                int rightDiff = array[max] - array[mid];
                                if(rightDiff > diff * (max - mid)) {
                                    if(max-mid == 1)
                                        return (array[max] + array[mid])/2;
                                    min = mid;
                                    missingNum = false;
                                    continue;
                                }
                                if(missingNum)
                                    break;
                            }
                            return -1;
                        }
                        

                      【讨论】:

                      • 什么AP?该代码采用数组“槽”值,而不考虑empty。在numbers are randomly added to the arraythe array should be sorted.. 之间,这看起来像the quickest way
                      【解决方案27】:

                      这里程序的时间复杂度是O(logn),空间复杂度是O(logn)

                      public class helper1 {
                      
                      public static void main(String[] args) {
                      
                      
                          int a[] = {1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12};
                      
                      
                          int k = missing(a, 0, a.length);
                          System.out.println(k);
                      }
                      
                      public static int missing(int[] a, int f, int l) {
                      
                      
                          int mid = (l + f) / 2;
                      
                          //if first index reached last then no element found 
                          if (a.length - 1 == f) {
                              System.out.println("missing not find ");
                              return 0;
                          }
                      
                          //if mid with first found 
                          if (mid == f) {
                              System.out.println(a[mid] + 1);
                              return a[mid] + 1;
                          }
                      
                          if ((mid + 1) == a[mid])
                              return missing(a, mid, l);
                          else
                              return missing(a, f, mid);
                      
                        }
                       }
                      

                      【讨论】:

                        【解决方案28】:
                        public class MissingNumber {
                        
                        public static void main(String[] args) {
                             int array[] = {1,2,3,4,6};
                             int x1 = getMissingNumber(array,6);
                            System.out.println("The Missing number is: "+x1);
                        
                        
                        }
                        private static int getMissingNumber(int[] array, int i) {
                        
                            int acctualnumber =0;
                            int expectednumber = (i*(i+1)/2);
                        
                            for (int j : array) {
                                acctualnumber = acctualnumber+j;
                        
                            }
                            System.out.println(acctualnumber);
                            System.out.println(expectednumber);
                            return expectednumber-acctualnumber;
                        
                        }
                        }
                        

                        【讨论】:

                        • 这是一个只提供代码的答案(当时没有注释),只提供了一半的结果。
                        【解决方案29】:

                        最近我在一次求职面试中遇到了一个类似(不完全相同)的问题,而且我从一位朋友那里听说,在一次面试中被问到了完全相同的问题。 因此,这是对 OP 问题的答案以及可能会提出的其他一些变体。 答案示例在 Java 中给出,因为它声明:

                        Java 解决方案更可取。

                        变体 1:

                        从 1 到 100(包括两个)的数字数组...这些数字被随机添加到数组中,但数组中有一个随机的空槽

                        public static int findMissing1(int [] arr){
                            int sum = 0;
                            for(int n : arr){
                                sum += n;
                            }
                            return (100*(100+1)/2) - sum;
                        }
                        

                        解释: 此解决方案(与此处发布的许多其他解决方案一样)基于 Triangular number 的公式,它为我们提供了从 1 到 n 的所有自然数的总和(在这种情况下,n 是 100)。现在我们知道应该从 1 到 100 的总和 - 我们只需要减去给定数组中现有数字的实际总和。

                        变体 2:

                        从 1 到 n 的数字数组(表示最大数未知)

                        public static int findMissing2(int [] arr){
                            int sum = 0, max = 0;
                            for(int n : arr){
                                sum += n;
                                if(n > max) max = n;
                            }
                            return (max*(max+1)/2) - sum;
                        }
                        

                        解释: 在这个解决方案中,由于没有给出最大数量 - 我们需要找到它。找到最大数量后 - 逻辑是相同的。

                        变体 3:

                        从1到n的数字数组(最大数未知),数组中有两个随机空槽

                        public static int [] findMissing3(int [] arr){
                            int sum = 0, max = 0, misSum;
                            int [] misNums = {};//empty by default
                            for(int n : arr){
                                sum += n;
                                if(n > max) max = n;
                            }
                            misSum = (max*(max+1)/2) - sum;//Sum of two missing numbers
                            for(int n = Math.min(misSum, max-1); n > 1; n--){
                                if(!contains(n, arr)){
                                    misNums = new int[]{n, misSum-n};
                                    break;   
                                }
                            }
                            return misNums;
                        }
                        private static boolean contains(int num, int [] arr){
                            for(int n : arr){
                                if(n == num)return true;
                            }
                            return false;
                        }
                        

                        解释: 在此解决方案中,未给出最大数字(如前所述),但它也可能缺少两个数字而不是一个。因此,首先我们找到缺失数字的总和 - 与之前的逻辑相同。第二次找到缺失总和和最后一个(可能)缺失的数字之间的较小数字 - 以减少不必要的搜索。第三,因为Javas 数组(不是集合)没有像indexOfcontains 这样的方法,所以我为该逻辑添加了一个小的可重用方法。第四,当找到第一个丢失的数字时,第二个是从丢失的总和中减去。 如果仅缺少一个数字,则数组中的第二个数字将为零。

                        变体 4:

                        从 1 到 n 的数字数组(最大数字未知),其中 X 缺失(缺失数字的数量未知)

                        public static ArrayList<Integer> findMissing4(ArrayList<Integer> arr){
                            int max = 0;
                            ArrayList<Integer> misNums = new ArrayList();
                            int [] neededNums;
                            for(int n : arr){
                                if(n > max) max = n;
                            }
                            neededNums = new int[max];//zero for any needed num
                            for(int n : arr){//iterate again
                                neededNums[n == max ? 0 : n]++;//add one - used as index in second array (convert max to zero)
                            }
                            for(int i=neededNums.length-1; i>0; i--){
                                if(neededNums[i] < 1)misNums.add(i);//if value is zero, than index is a missing number
                            }
                            return misNums;
                        }
                        

                        解释: 在这个解决方案中,和前面一样,最大数量是未知的,并且可能会丢失多个数字,但在这个变体中,我们不知道有多少个数字可能丢失(如果有的话)。逻辑的开头是相同的 - 找到最大数量。然后我用零初始化另一个数组,在这个数组中index 表示可能丢失的数字,零表示数字丢失。因此,原始数组中的每个现有数字都用作索引,其值加一(最大值转换为零)。

                        注意

                        如果您想要其他语言或其他此问题的有趣变体的示例,欢迎您查看我的Github 存储库以获取Interview questions & answers

                        【讨论】:

                        • 在第二个变体中,我们可以将max设置为arr.length() + 1,而不是检查(n> max)条件,n次
                        • 你为什么要找到最大值,只需跟踪数组中缺少多少整数并将其添加到数组长度中。
                        • @akshattailang 如果你不知道最大值,你怎么知道丢失了多少?
                        【解决方案30】:

                        使用求和公式,

                        class Main {
                        // Function to ind missing number
                             static int getMissingNo (int a[], int n) {
                                  int i, total;
                                  total  = (n+1)*(n+2)/2;   
                                  for ( i = 0; i< n; i++)
                                      total -= a[i];
                                  return total;
                             }
                        
                            /* program to test above function */
                            public static void main(String args[]) {
                        
                                int a[] = {1,2,4,5,6};
                                int miss = getMissingNo(a,5);
                                System.out.println(miss);   
                           }
                        }
                        

                        参考http://www.geeksforgeeks.org/find-the-missing-number/

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2014-01-31
                          • 1970-01-01
                          • 2022-12-03
                          • 2014-04-19
                          • 2011-11-11
                          相关资源
                          最近更新 更多