我的问题是,如何在 c 中遍历一次元素后忽略它

问题描述

[由于我是初学者,我没有得到这个答案,在这种情况下,2 被计算为 4 次,但它也在再次计算数组中 2 的重复元素。]

//用C编写一个程序,找出数组中出现奇数次的数字 please check the image of what I am asking drawn in paint

找出所有出现奇数次的元素。

#include <stdio.h>

#define MAX 100

int main() {
    int arr[MAX],n,i;
    printf("Enter size of array : ");
    scanf("%d",&n);
    printf("Enter element in array : ");
    for (i = 0; i < n; i++) {
        printf("index - [%d] : ",i);
        scanf("%d",&arr[i]);
    }
    int count;
    
    for (i = 0; i < n; i++) {
        count = 0;
        for (int j = 0; j < n; j++) {
            if (arr[i] == arr[j]) {
                count++;
            }
        }
        if (count % 2 != 0) {
            printf(" %d ",arr[i]);
        }
    }
    if (count % 2 == 0)
        printf("No elements appeared odd times in array .");
    else
        printf(" appeared odd times in array . ");
}

解决方法

有很多方法可以做到这一点,

我会先对数组进行排序。在此处查找不同类型的算法:https://www.educba.com/sorting-in-c/

然后编写代码遍历每组数字并确定 x 是否为偶数,然后移动到下一组 x。

,

当发现重复次数为奇数的元素时,您不会中断循环。

如果不允许在循环的时候改变数组可以看下面的方法

int count = 0;

for ( i = 0; i < n && count % 2 == 0; i += count == 0 )
{
    count = 0;
    int j = 0;

    while ( j < i && a[j] != a[i] ) j++;

    if ( j == i )
    {
        count ^= 1;
        while ( ++j < n )
        {
            if ( a[j] == a[i] ) count ^= 1;
        }
    }    
}

if ( count )
{
    printf( "%d appeared odd times in array.\n",a[i] );
}
else
{  
    puts( "No elements appeared odd times in array." );
} 

这是一个基于你的代码编写的演示程序

#include <stdio.h>

int main( void ) 
{
    int a[] = { 1,2,1,3,2 };
    int n = ( int )( sizeof( a ) / sizeof( *a ) );
    int i;  
    int count = 0;

    for ( i = 0; i < n && count % 2 == 0; i += count == 0 )
    {
        count = 0;
        int j = 0;

        while ( j < i && a[j] != a[i] ) j++;

        if ( j == i )
        {
            count ^= 1;
            while ( ++j < n )
            {
                if ( a[j] == a[i] ) count ^= 1;
            }
        }    
    }

    if ( count )
    {
        printf( "%d appeared odd times in array.\n",a[i] );
    }
    else
    {  
        puts( "No elements appeared odd times in array." );
    } 
    
    return 0;
}

程序输出为

2 appeared odd times in array.
,

假设数组中只有一个数字出现奇数次,可以使用 O(n) 时间复杂度解决它,只需使用 XOR 进行一次遍历,如上所述。

假设整数的范围是有限的,例如您知道所有数字都在 [-k,k] 范围内,然后可以使用 LUT(查找表)在 O(n+k) 中求解。如果 n 总是大于 k,那么你可以说它是“O(n)”。

否则,我认为没有办法在 O(n) 中解决这个问题。 在最坏的情况下,所有数字在数组中出现一次(这是奇数次),这意味着在遍历数组的每次迭代中,您都需要存储遇到的值并检查它之前是否已经出现过,并且这些操作在没有查找表的情况下至少需要 O(log(n))。 因此,完整算法最多将具有 O(n log(n)) 时间复杂度,在这种情况下,仅对数组进行排序会更容易,正如 Cam Klein 所说。即使你只允许遍历原始数组一次,你也可以将它复制到另一个数组或数据结构中并对其进行排序。

使用查找表的解决方案,假设数组中的所有值都在 [0,100] 范围内,将如下所示:

#include <stdio.h>

#define MAX 100
#define MIN_RANGE 0
#define MAX_RANGE 100

int main() {
    int arr[MAX],n,i;
    static int lut[MAX_RANGE - MIN_RANGE + 1]
    printf("Enter size of array : ");
    scanf("%d",&n);
    printf("Enter element in array : ");
    for (i = 0; i < n; i++) {
        printf("index - [%d] : ",i);
        scanf("%d",&arr[i]);
    }
    int count = 0;
    
    for (i = 0; i < n; i++) {
        lut[arr[i] - MIN_RANGE] += 1;
    }
    
    for (i = MIN_RANGE; i <= MAX_RANGE; i++) {
        if (lut[i] % 2 == 1) {
             ++count;
             printf("%d appeared odd times in array.\n",i);
        }
    }
    if (count == 0)
    {  
        puts("No elements appeared odd times in array.");
    } 
}