在数字数组中查找缺失数字的最快方法


67

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


3
实际上我知道一种解决方案-从1-100中找到数字总和,然后从数组中的数字总和中减去以获得缺少的数字。我很想知道是否还有其他有趣的解决方案。
Thunderhashy

2
空的值是多少?0?-1?
MAK 2010年

3
采访中有人问我这个问题
Foo Bah

我认为sayro的答案在这种情况下是最好的
antnewbee

2
如果您的整数不是从1开始怎么办?例如{15,16,17,19,20}?
CBC_NS 2015年

Answers:


146

您可以在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);

您可以记下第一次迭代时任何索引为零。
托尔比约恩Ravn的安德森

27
求和是整数溢出的素数,以下方法应加以注意:对所有给定数字进行XOR运算,将此X1 XOR与从1到100的所有数字称为X1 X2 X1 XOR X2应该是缺失的数字,因为所有重复的数字异或。
Abhinav Sharma

18
@AbhinavSharma是的,但是如果溢出能很好地包装,则它也可用于求和,只要溢出能很好地包装即可,这在Java中是保证的,对于无符号类型则在C中得到保证。
丹尼尔·菲舍尔

11
在这种情况下,总数应为(arr.length +1)*(arr.length + 2)/ 2以满足n *(n +1)/ 2,因为对于大多数语言而言,数组索引从0开始,我们需要将长度增加1
dvliman 2014年

3
对于此扫描仪,请考虑缺少大约2个数字。您有什么解决方案?
EmreGürses'3

32

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

在寻求解决方案之前,请知道A xor A = 0。因此,如果我们对两个相同的数字进行XOR运算,则该值为0。

现在,对数组中存在的元素进行XORing [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. 

2
独特的解决方案。我也喜欢它如何处理潜在的溢出情况。
塞浦路斯

2
什么是XOR初始值?
Dejell '16

@Dejell,它应该为零。
Maria Ines Parnisari '16

这种使用XOR的解决方案仅在将所有元素都按数组排序时才有效,但是在给定的问题中,元素是随机顺序的。
安尼尔·库玛

3
您的答案不适用于以下输入int arr1 [] = {1,3,4,5}; int XOR = 0; for(int i = 0; i <arr1.length; i ++){if(arr1 [i]!= 0)XOR ^ = arr1 [i]; XOR ^ =(i + 1); 返回XOR;理想的答案应该是2。但在这种情况下,答案是7. @ DungeonHunter
Prajyod Kumar,

23

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

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

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

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

算法1:

在算法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:尽管第二个实现的公式是从第一个实现的公式得出的,但从数学角度来看两者都是相同的。但是从编程的观点来看,两者都是不同的,因为第一个实现的公式比第二个实现的公式更容易发生位溢出(如果给定的数字即使加法的速度比减法的速度还快,但是第二种实现减少了由大数值的加法导致的位溢出的机会(它没有完全消除,因为N+1公式中有()的机会仍然很小)但是,两者同样容易因乘法而发生位溢出。其局限性在于,两个实现仅在时才给出正确的结果N(N+1)<=MAXIMUM_NUMBER_VALUE。对于第一个实现,另外的局限性是仅当Sum of all given numbers<=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)大。

算法2:

我们可以使用XOR的属性来获得此问题的解决方案,而不必担心位溢出的问题。而且XOR比求和更安全,更快速。我们知道XOR的性质,即两个相同数字的XOR等于0(A XOR A = 0)。如果我们计算从1到N的所有数字的XOR(包括未知的遗漏数字),然后对所有给定的数字进行XOR运算,则公共数字将被抵消(因为A XOR A=0)最后得到丢失的数字数。如果没有位溢出问题,则可以使用求和和基于XOR的算法来获取解决方案。但是,使用XOR的算法比使用求和,减法和乘法的算法既安全又快速。而且,我们可以避免因求和,减法和乘法而引起的额外麻烦。

在算法1的所有实现中,我们可以使用XOR代替加法和减法。

假设 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运算的数量,而不是通过对所有从1到N的数字进行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);

12
这个答案看起来很有趣,但是还需要更多解释。
gsingh2011 2013年

5
数字本身的Xor为零。因此,如果我们对数组中所有从1到n的所有数字进行异或运算,我们将只剩下缺失的数字
Aditya

12
请问有人可以解释为什么初始值需要以4为模的模吗?
jschank 2014年

4
@jschank:这是您计算总和时的n(n + 1)/ 2的类似物。您可以通过感应证明1 xor 2 xor ... xor n要么n1n + 10根据n % 4
克莱门特

1
这是最好的答案。
伊夫

17

这是一个亚马逊面试问题,最初在这里得到回答:我们将1到52的数字放入一个51的数字数组中,找出丢失哪个数字的最佳方法是什么?

回答如下:

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-面试问题


我尝试用1,2,3和5作为序列。(即4是丢失的数字)。值的总和是11,所以我做了((11 * 12)/ 2)-11,我得到了55。为什么我没有得到4?
ziggy 2012年

n是数字数。因此,它应该是5 *(5 + 1)/ 2 = 15 ...和15 - (1 + 2 + 3 + 5)= 4
bchetty

n是数字的个数,所以应该是4(1,2,3&5)。你怎么得到5的最大数字。
SidD 2015年

@mparnisari是的,这就是为什么我在这里发布,因为我认为原始帖子(我在博客上发布)没有任何荣誉(参考)。我经历了几次,因为有些人只是复制代码并按原样发布(就像在我的博客上一样),甚至没有引用原始帖子。顺便说一句,感谢负/负点!
bchetty

@SidD n是系列1…N中最大的数字
Avinash

13

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

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);
}

1
我检查了这里编写的每个函数,这是唯一起作用的函数!谢谢。
IamStalker 2015年

正如@MladenOršolić指出的那样,如果数组中的数字不是按排序顺序排列的,则您的解决方案将无法工作。因此,为了使用您的解决方案,对数组进行排序是前提条件
foxt7ot

这是一个很好的解决方案。
Kumaresan Perumal

6

(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);

2
5050是什么?给定包含1,2,0,4,5的数组,此代码似乎不起作用。
core_pro 2012年

6
@core_pro示例数组的大小为5,而不是指定的OP 100。5050是1到100的所有整数的总和,适用于具有100个元素的数组。因此,对于大小为5的数组,等效
值为15。– CodesInChaos

5

最近,我在一次求职面试中遇到了一个类似(不完全相同)的问题,而且我还从一个朋友那里听到面试中被问到完全相同的问题。因此,这是对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;
}

说明: 在此解决方案中,没有给出最大数(如前所述),但也可能缺少两个数字而不是一个。因此,首先,我们发现缺失数字的总和-与以前的逻辑相同。第二,找到丢失的总和与最后(可能)丢失的数字之间的较小数字-减少不必要的搜索。第三,因为JavaArray(不是Collection)没有asindexOf或as方法contains,因此我为该逻辑添加了一个可重用的小方法。第四个是找到第一个缺失数时,第二个是从缺失总和中减去。如果仅缺少一个数字,则数组中的第二个数字将为零。

变体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表示可能丢失的数字,而零表示该数字丢失。因此,原始数组中的每个现有数字都将用作索引,并且其值将增加1(最大值转换为零)。

注意

如果您想要其他语言的示例或该问题的其他有趣变体,欢迎访问我的Github资源库以获取面试问题和解答


在第二个变量中,我们可以将max设置为arr.length() + 1
Aman

为什么要查找最大值,只需跟踪数组中缺少多少个整数并将其添加到数组长度即可。
akshat tailang

@akshattailang如果不知道最大值,又如何知道缺少多少?
Nikita Kurtin

4

在类似的情况下,该数组已被排序,它不包括重复项,并且仅缺少一个数字,可以使用二进制搜索在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
}

1
好人,你能解释一下为什么我们需要[-(右-左)%2]
craftsmannadeem

我同意,这是我看到的针对此类算法的最佳解决方案之一。我也想出于好奇而对(右-左)%2进行解释。
FuegoJohnson

3

好吧,使用布隆过滤器。

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;
}

2

这是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;

2

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

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

  1. 遍历数字数组并将1设置为与该数字对应的位位置(例如,将在从左到右的第7位的第3个int处设置71)
  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​​(所有位均已设置),因此,我们继续进行第二个int,并将数字32加为“ no”。第二个int与-1(未设置位)不同,因此,通过应用我们用64的幂来表示2。在这种情况下,我们得到log2(64)= 6 => 32 + 32-6 = 58。

希望这可以帮助。


1

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


1

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

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循环。
广播

1

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

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与接受的答案共享了对总数的可疑使用,但它与它有什么不同,它又增加了什么呢?
greybeard

这是我一直在寻找的最简单的逻辑答案!谢谢您:)
Shekhar Swami

很高兴为您提供了帮助Shekhar :)
Bhavin Shah

1
function solution($A) {
    // code in PHP5.5
    $n=count($A);
    for($i=1;$i<=$n;$i++) {
       if(!in_array($i,$A)) {
              return (int)$i;
       }
    }
}

1
请考虑在说明中进行编辑-否则,审阅者会将您的答案标记为“低质量”。
OhBeWise

1

从一系列数字中找到丢失的数字。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?该代码采用数组“ slot”值,而empty与否无关。在numbers are randomly added to the array和之间the array should be sorted..,看起来the quickest way如何?
灰胡子

0

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


0

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

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);
}

}

0

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

在上面的序列中,没有缺失的数字,并且每列中的零和一的数目都匹配,但是,一旦您删除1值,就说3,我们在两列中获得了0和1的平衡。如果一列中的0数<= 1的数,则我们在该位位置的缺失数将为0;否则,如果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


0

此处程序的时间复杂度为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);

  }
 }

0
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;

}
}

这是仅代码的答案(当时还没有评论),仅提供一半的结果。
灰胡子


0
simple solution with test data :

class A{

  public static void main(String[] args){
    int[] array = new int[200];
    for(int i=0;i<100;i++){
      if(i != 51){
        array[i] = i;  
      }
    }

    for(int i=100;i<200;i++){
      array[i] = i;  
    }

    int temp = 0;
    for(int i=0;i<200;i++){
      temp ^= array[i];
    }

    System.out.println(temp);
  }
} 

-1
    //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**

-1

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


2
那不能回答如何找出丢失的号码。
哨兵

-1

该程序发现丢失的数字

<?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下提出。然而,由于真正的算法始终与语法无关,所以它可以保留在这里:)
Ankur 2013年

-1

现在,我对Big O表示法太过敏锐,但是您也不能做类似的事情(在Java中)

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

其中number是您的数字从1到100的数组。从我对问题的阅读中,它没有说出何时写出缺失的号码。

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

当然,它可能不遵守时间和空间规则。就像我说的。我必须大力复习BigO。


1
OP表示,数组中的数字可以不排序
-Sentry

对于输入(0,1),这将失败
Ahmed Saleh 2015年

-1

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

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;
        }

-6

另一个作业问题。顺序搜索是您最好的选择。至于Java解决方案,请为读者准备一个练习。:P

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.