在整数序列中查找第一个缺失的整数
缺少[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
任何人都可以帮助我找到一个涵盖所有这些情况的好的算法。我有一个算法可以涵盖前两种情况,但不确定如何有效地涵盖所有情况。
答案 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);
因此,您将key
和value
放在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是最小的遗漏数。