问题描述
|
给定大小为n的数组。它包含1到n范围内的数字。每个数字都在
除2个数字外,至少一次。查找丢失的数字。
例如。大小为5的数组
元素假定为3,1,4,3
一种方法是
static int k;
for(i=1;i<=n;i++)
{
for(j=0;j<n;j++)
{
if(i==a[j])
break;
}
if(j==n)
{
k++;
printf(\"missing element is\",a[j]);
}
if(k==2)
break;}
另一个解决方案可以..
对于(i = 0; i
解决方法
使用ѭ1排序数组,然后在其上循环一次以查找丢失的值。由于排序的原因,平均O(n * log(n))时间以及最少的恒定额外存储量。
,首先让我解释一下这个概念:
你知道自然数之和1 .... n是
(n *(n + 1))/ 2。也知道前n个自然数1,2,...的平方和是n *(n + 1)*(2n + 1)/ 6因此,您可以使用上述概念在O(n)时间内解决上述问题。
同样,如果对空间复杂度的考虑不多,则可以使用基于计数的方法,这需要O(n)的时间和空间复杂度。
有关更详细的解决方案,请访问在给定数组中查找两个重复元素
,我喜欢Algorithmist链接中的“将数组元素用作索引”方法。
方法5(使用数组元素作为索引)
感谢Manish K. Aasawat提出了此方法。
traverse the list for i= 1st to n+2 elements
{
check for sign of A[abs(A[i])] ;
if positive then
make it negative by A[abs(A[i])]=-A[abs(A[i])];
else // i.e.,A[abs(A[i])] is negative
this element (ith element of list) is a repetition
}
唯一的区别是,这里将遍历1到n。
请注意,这是一个不占用额外空间的单遍解决方案(除了存储i
)!
脚注:
从技术上讲,它“窃取”了一些额外空间-本质上是计数器数组解决方案,但是它没有分配自己的整数数组,而是使用原始数组的符号位作为计数器。
,我没有检查或运行此代码,但是您应该明白这一点。
int print_missing(int *arr,size_t length) {
int *new_arr = calloc(sizeof(int) * length);
int i;
for(i = 0; i < length; i++) {
new_arr[arr[i]] = 1;
}
for(i = 0; i < length; i++) {
if(!new_arr[i]) {
printf(\"Number %i is missing\\n\",i);
}
}
free(new_arr);
return 0;
}
运行时应为O(2n)。如果我错了纠正我。
,目前尚不清楚为什么天真的方法(您可以使用位域或数组)来标记您所看到的项目并不只是很好。 O(2n)CPU,O(n / 8)存储。
,如果您可以自由选择语言,请使用python \'s set。
numbers = [3,1,4,3]
print set (range (1,len (numbers) + 1) ) - set (numbers)
产生输出
set([2,5])
,干得好。 C#解决方案:
static IEnumerable<int> FindMissingValuesInRange( int[] numbers )
{
HashSet<int> values = new HashSet<int>( numbers ) ;
for( int value = 1 ; value <= numbers.Length ; ++value )
{
if ( !values.Contains(value) ) yield return value ;
}
}
,我发现您的代码存在许多问题。首先,j==n
永远不会发生,这不会给我们遗漏的号码。尝试将initialize9ѭ初始化为0之前,还应将其初始化为0。我写了一个与您相似的算法,但是可以正常工作。但是,它并没有比您期望的更快:
int k = 0;
int n = 5;
bool found = false;
int a[] = { 3,3 };
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < n; j++)
{
if(a[j] == i)
{
found = true;
break;
}
}
if(!found)
{
printf(\"missing element is %d\\n\",i);
k++;
if(k==2)
break;
}
else
found = false;
}
H2H
,使用支持数组可以归档O(n)
int support[n];
// this loop here fills the support array with the
// number of a[i]\'s occurences
for(int i = 0; i < n; i++)
support[a[i]] += 1;
// now look which are missing (or duplicates,or whatever)
for(int i = 0; i < n; i++)
if(support[i] == 0) printf(\"%d is missing\",i);
,**
for(i=0; i < n;i++)
{
while((a[i]!=i+1)&&(a[i]!=a[a[i]-1])
{
swap(a[i],a[a[i]-1]);
}
for(i=0;i< n;i++)
{
if(a[i]!=i+1)
printf(\"%d is missing\",i+1); }
this takes o(n) time and o(1) space
====================================== **
,我们可以使用以下代码查找重复和缺失的值:
int size = 8;
int arr[] = {1,2,3,5,3};
int result[] = new int[size];
for(int i =0; i < arr.length; i++)
{
if(result[arr[i]-1] == 1)
{
System.out.println(\"repeating: \" + (arr[i]));
}
result[arr[i]-1]++;
}
for(int i =0; i < result.length; i++)
{
if(result[i] == 0)
{
System.out.println(\"missing: \" + (i+1));
}
}
,这是一个面试问题:数字缺失。
条件1:数组不得包含任何重复项。
完整的解决方案是:
public class Solution5 {
public static void main(String[] args) {
int a[] = { 1,8,6,7,10};
Arrays.sort(a);
List<Integer> list = new ArrayList<>();
int start = a[0];
for (int i = 0; i < a.length; i++) {
int ch = a[i];
if(start == ch) {
start++;
}else {
list.add(start);
start++;
//must do this
i--;
}
}//for
System.out.println(list);
}//main
}