缺少数字

时间:2011-05-25 18:28:58

标签: c range elements

给出一个大小为n的数组。它包含1到n范围内的数字。每个号码都出现在 至少一次,除了2个号码。找到缺少的数字。 例如。一个5号的数组 元素是假设3,1,4,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;我

12 个答案:

答案 0 :(得分:4)

首先让我解释概念

你知道自然数的总和1 .... n是 (n *(n + 1))/ 2 。另外你知道前n个自然数的和的平方和1,2 .... n是 n *(n + 1)*(2n + 1)/ 6 。因此,您可以使用上述概念在O(n)时间内解决上述问题。

如果不考虑空间复杂性,您可以使用基于计数的方法,这需要O(n)时间和空间复杂度

有关更详细的解决方案,请访问Find the two repeating elements in a given array

答案 1 :(得分:2)

我喜欢Algorithmist的link中的“使用数组元素作为索引”方法。

  

方法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)!

脚注:

技术上它“窃取”了一些额外的空间 - 本质上它是计数器阵列解决方案,但它不是分配自己的整数数组,而是使用原始数组的符号位作为计数器。

答案 2 :(得分:1)

我没有检查或运行此代码,但您应该明白这一点。

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)。如果我错了,请纠正我。

答案 3 :(得分:1)

使用qsort()对数组进行排序,然后循环一次以查找缺失值。平均O(n * log(n))时间,因为排序和最小的常量额外存储。

答案 4 :(得分:0)

目前还不清楚为什么标记你看过的物品的天真方法(你可以使用比特场或数组)并不合适。 O(2n)CPU,O(n / 8)存储。

答案 5 :(得分:0)

如果您可以自由选择语言,请使用python的集合。

numbers = [3,1,4,4,3]
print set (range (1 , len (numbers) + 1) ) - set (numbers)

产生输出

set([2, 5])

答案 6 :(得分:0)

你走了。 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 ;
  }
}

答案 7 :(得分:0)

我发现您的代码存在许多问题。首先,j==n将永远不会发生,并且这不会给我们丢失的号码。在尝试递增之前,还应将k初始化为0。我写了一个类似于你的算法,但它可以正常工作。但是,它并不比你预期的更快:

int k = 0;
int n = 5;
bool found = false;
int a[] = { 3, 1, 4, 4, 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

答案 8 :(得分:0)

使用支持数组,您可以存档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);

答案 9 :(得分:0)

**

 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

======================================== **

答案 10 :(得分:0)

我们可以使用以下代码查找重复值和缺失值:

    int size = 8;
    int arr[] = {1, 2, 3, 5, 1, 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));
        }
    }

答案 11 :(得分:0)

这是一个采访问题:缺少数字。 条件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

}