算法-在整数序列中查找第一个缺失的整数

时间:2019-03-08 06:44:49

标签: algorithm

在整数序列中查找第一个缺失的整数

缺少[4,5,1,2,6,7]是3

然后是重复的整数

[1,2,2,2,5,8,9]仍然缺少3

当你也有否定

[-2,0,1,2,]缺少-1

[1,2,3,4,5]缺少6或0

任何人都可以帮助我找到一个涵盖所有这些情况的好的算法。我有一个算法可以涵盖前两种情况,但不确定如何有效地涵盖所有情况。

4 个答案:

答案 0 :(得分:2)

对于这个问题,我认为经典的O(n)解决方案是基于这样一个事实,即数组最多可以包含N个唯一数字,其中N是输入的长度。因此,我们的记录范围仅限于N

由于您似乎允许期望的序列在任何地方(包括负数)开始,因此我们可以在数组上进行一次迭代并记录L,这是看到的最低数字。现在使用L作为偏移量,以便0 + L等于我们期望出现的第一个数字。

初始化长度为(N + 1)的数组记录,并将每个条目设置为false。遍历输入,对于每个条目A[i],如果(A[i] - L)不大于N,则将record[ A[i] - L ]设置为true。例如:

[-2, 0, 1, 2] ->
N = 4
L = -2

-2 -> -2 - (-2) = 0
   -> record[0] = true

 0 -> 0 - (-2) = 2
   -> record[2] = true

 1 -> 1 - (-2) = 3
   -> record[3] = true

 2 -> 2 - (-2) = 4
   -> record[4] = true

record -> [true, false, true, true, true]

现在遍历记录。在索引i处将设置为false的第一项输出为i + L。在上面的示例中,这将是:

record[1] is false

output: 1 + (-2) -> -1

答案 1 :(得分:2)

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() 
{   
int n;
scanf("%d",&n);
int a[n],i=0;
//Reading elements
for(i=0;i<n;i++){
    scanf("%d",&a[i]);
}
int min=__INT_MAX__,max=0;
//Finding the minimun and maximum from given elements
for(i=0;i<n;i++){
    if(a[i]>max)
    max=a[i];
    if(a[i]<min)
    min=a[i];
}
int len=max-min,diff=0-min,miss;
int b[len];
//Creating a new array and assigning 0
for(i=0;i<len;i++)
    b[i]=0;
//The corresponding index value is incremented based on the given numbers
for(i=0;i<n;i++){
    b[a[i]+diff]++;
}
//Finding the missed value
for(i=0;i<len;i++){
    if(b[i]==0){
        miss=i-diff;
        break;
    }
}
printf("%d",miss);
}

代码说明:


1。查找给定数字中的最小值和最大值。

2。创建一个大小为(最大-最小)的计数数组,并初始化为0,以保持给定数字的计数。

3。现在,通过迭代,对于每个给定的元素,将对应的索引增加1。

4。最后遍历count数组,找到第一个缺失的数字。

这可能会帮助您解决问题。如果我错了,请纠正我。

答案 2 :(得分:1)

我认为,使用JAVA中的TreeMap这样的数据结构来解决各种问题很容易,例如:

treeMap.put(array[i], treeMap.get(array[i]) == null ? 1 : treeMap.get(array[i]) + 1);

因此,您将keyvalue放在TreeMap上,key代表数字本身,例如 1,2,3 ... < / em>和value代表出现时间。

因此,利用此数据结构(对我们来说是排序元素),您可以遍历该数据结构并检查序列中缺少哪个键,例如:

for key in treeMap
   if(key > currentIndex) // this is the missing digit
   if(loop-completed-without-missing-key) // it's not in the array.

答案 3 :(得分:1)

将数字添加到正在运行的数组中,并使它们保持排序。

对于数组,您可能还具有可选的最小和最大边界(为处理第三种情况,“即使不在数组中也缺少6”

在检查新号码时:   -尝试将其插入排序数组中。     -已经存在:丢弃     -低于最小值或高于最大值:相应地取消最小值或最大值     -否则请添加适当的位置。

要处理数组:将其排序,将第一个和最后一个元素与期望的最小/最大比较。如果大于第一个元素,则使最小值无效;如果小于最后一个元素,则使最大值无效。

如果最小值和最大值都在第一位以上或两者都在末位以上,则可能是可能的特殊情况:

 min=5 max=8   array = [ 10, 11, 13 ]

 Here 5, 6, 7, 8 and 12 are missing, but what about 9? Should it be considered missing?

检查缺少的数字时,包括:     -如果minimum不为null,则从最小值到第一个元素的所有数字。     -如果maximum不为null,则从最后一个元素到max的所有数字。     -如果(最后-第一个)=元素数量,则不丢失任何数量       (检查的总数减去数组大小即为重复计数)     -否则遍历数组并报告所有缺失的数字:何时       检查array [i],如果array [i] -array [i-1]!= 1表示您有空隙。

仅缺少“第一个”

即使您只对一个缺失的数字感兴趣,仍然必须管理整个阵列。因为如果您丢弃了数组的一部分,而丢失的数字到了,那么 new 丢失的数字很可能已经在数组的废弃部分中。

但是,您可能会跟踪丢失的最小数 的数量,并仅在到达时(如果到达)以o(log n)的成本进行重新计算;那么您就能在o(1)时间内知道是哪个。要快速使该缺失数为零,请考虑到arr [i]和arr [j]之间的差距,而arr [j] -arr [i]> j-i。

因此,您可以使用二等分方法:以i =首先,j =最后;如果gap(i,j),则c = ceil(i + j)/ 2。如果gap(i,c)则j = c,否则i = c,并重复直到j-i =1。这时,arr [i] +1是最小的遗漏数。