C语言习题:有10X个整数,其中有50个数出现了两次,X个数出现了一次, 找出出现了一次的那X个数。

(1)有101个整数,其中有50个数出现了两次,1个数出现了一次, 找出出现了一次的那个数。
(2)有102个整数,其中有50个数出现了两次,2个数出现了一次, 找出出现了一次的那2个数。
(3)有103个整数,其中有50个数出现了两次,3个数出现了一次, 找出出现了一次的那3个数。

#include <stdio.h>
#define MAX 20
int case1(int arr[], int length);               
void case2(int arr[], int length, int res[]);
void case3(int arr[], int length, int res[]);
int main()
{
	int arr1[] = { 1,2,2,3,3,4,4,5,5,6,6 };
	int res1;
	res1 = case1(arr1, sizeof(arr1) / sizeof(int));

	int arr2[] = { 1,2,3,3,4,4,5,5,6,6,7,7 };
	int res2[2];
	case2(arr2, sizeof(arr2) / sizeof(int), res2);

	int arr3[] = { 2,4,6,9,9,5,5,10,10,7,7,8,8 };
	int res3[3];
	case3(arr3, sizeof(arr3) / sizeof(int), res3);

	return 0;
}
int case1(int arr[], int length)
{
	int xorRes = 0;
	for (int i = 0; i < length; ++i)
	{
		xorRes ^= arr[i];   //采用异或运算,异或运算满足交换律,并且一个数和自身异或为0,和0异或为其本身
	
	}
	return xorRes;
}
void case2(int arr[], int length, int res[])
{
	int xorRes = case1(arr, length);
	int divider = xorRes & -xorRes;  //找到两个不相等的数一个bit为1的位置(最高位)
	int heap1[MAX] = { 0 };
	int length1 = 0;                //将这个数组分成两堆数据,这两堆数据中分别包含互不相等的数字
	int heap2[MAX] = { 0 };
	int length2 = 0;
	for (int i = 0; i < length; ++i)
	{
		if (arr[i] & divider)      //如果arr[i]和divider&结果为1,说明arr[i]的那个bit位也为1
		{
			heap1[length1++] = arr[i];
			//0,1,2,。。。length1-1
		}
		else                      //如果arr[i]和divider&结果为1,说明arr[i]的那个bit位为0
		{
			heap2[length2++] = arr[i];
		}
	}
	res[0] = case1(heap1, length1);
	res[1] = case1(heap2, length2);
}
void case3(int arr[], int length, int res[])
{ 
	int divider = 1;               // 测试divider能否成功分堆,不能的话 divider <<= 1
	int heap1[MAX] = { 0 };
	int length1 = 0;
	int heap2[MAX] = { 0 };
	int length2 = 0;
	for (int pos = 1; pos < sizeof(int) * 8; ++pos, divider <<= 1)     //共32位bit,遍历32位的每一个bit为1时,能否将数据成功分成两堆
	{
		length1 = 0;
		length2 = 0;
		for (int i = 0; i < length; ++i)       //采用case2中的方法尝试分堆
		{
			if (arr[i] & divider)
			{
				heap1[length1++] = arr[i];
			
			}
			else
			{
				heap2[length2++] = arr[i];
			}
		}

		if (length1*length2)                  //如果length1和length2都不为0,尝试将数据分成两堆
		{
			int xorRes1 = case1(heap1, length1);   
			int xorRes2 = case1(heap2, length2);
			if (xorRes1 * xorRes2)            //如果xorRes1和xorRes2的都不为0,说明分堆成功,一堆含有1个数字,一堆含2个数字
			{
				if (length1 % 2 == 0)         //第一堆为偶2个,第二堆则为1个
				{
					res[0] = xorRes2;         //将第二堆数据的异或结果赋值给res[0]
					case2(heap1, length1, res + 1);       //再调用case2()函数解决heap1,需要传入res+1即res[1]的地址
				}
				else
				{
					res[0] = xorRes1;
					case2(heap2, length2, res + 1);
				}
				break;              //成功解决问题
			}
			else
			{
				continue;
			}
		}
		else
		{
			continue;
		}
	}
}

另一种通用解法可以讲数组中的元素导入到结构体,向结构体中添加一个计数器就可以解决问题。

#include<iostream>
#include<string>
using namespace std;
struct MyArray {
	int data;
	int count = 0;     //对data出现的次数进行计数
};
int main() {
	MyArray array[100];
	int p = 0;
	for (int i = 0; i < 10; i++) {            //此处只测试10个数据
		int flag = 1;      //标记位
		int num;
		cin >> num;
		for (int j = 0; j < p; j++) {        //对当前输入数字之前的数字进行遍历
			if (array[j].data == num) {        //如果发现存在和当前数字相等的数字,将标志位置为0
				array[j].count++;          
				flag = 0;
				break;
			}
		}
		if (flag == 1) {            //说明当前输入的数字在array中未出现过
			array[p].data = num;
			array[p].count = 1;
			p++;                  //array中不同数字的数量
		}
	}
	for (int i = 0; i < p; i++) {
		if (array[i].count == 1) {
			cout << array[i].data << endl;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值