问题描述
[由于我是初学者,我没有得到这个答案,在这种情况下,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.");
}
}