NC156 数组中只出现一次的数(其它数出现k次)

题目描述:

给定一个长度为  的整型数组 arr和一个整数k(k>1) 。

已知  中只有 1 个数出现一次,其他的数都出现 k 次。

请返回只出现了 1 次的数。

输入:[5,4,1,1,5,1,5],3                返回值:4

目录

 思路1:(暴力求解)

思路2:(位运算)

思路3:(排序法)

思路4:(异或方法)


 思路1:(暴力求解)

以每一个数去遍历整个数组,碰到相同的数就记下来,遍历完后,判断记下的数等不等于k,等于就判断下一个数,不等于就直接返回这个数。

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param arr int一维数组
 * @param arrLen int arr数组长度
 * @param k int
 * @return int
 */
int foundOnceNumber(int* arr, int arrLen, int k) {
	for (int i = 0; i < arrLen; i++) {
		int count = 0;//计数器
		for (int j = 0; j < arrLen; j++) {
			if (arr[i] == arr[j])
				count++;
		}
		if (count == 1)//只出现了一次的数
			return arr[i];
	}
	return -1;
} 

思路2:(位运算)

把每个数化为32位的二进制形式来运算,计算出原数组数字的相同比特位上的1的出现总次数之和,因为如果一个数出现了k次,那么他的相同比特位上就有k个1,所以用次数这和模k来判断是否出现了k次,次数模k如果等于0,说明是重复出现的数字,如果不为0,说明只出现了一次,那么把这一位的1还原再加上其他位的1还原就能得到原来的数。

比如:【1,1,2,2,3】,k=2

比特位:001,001,010,010,011

第一位上出现1的总次数是:3

第二位上出现1的总次数是:3

第一位上:3%k!=0也就是说 3不是k的倍数,说明那个没重复的数字的这一位上是1

第二位上:同上,重复的数字的这一位上也是一个1

那么利用位运算将这两个比特位上的1进行还原,然后相加就得到原来的数就是没有重复的数。

如图:

 代码及详情如下:

int foundOnceNumber(int* arr, int arrLen, int k) {
//新建一个大小为32的数组,用来记录每一比特位上1出现的次数
	int bit[32];
//外循环是比特位上循环
	for (int i = 0; i < 32; i++) {
//相当于一个计数器
		bit[i] = 0;
//内循环是数组元素循环
		for (int j = 0; j < arrLen; j++) {
//先右移i位,再&1就能算出当前比特位上的数字是1还是0
			bit[i] += (arr[j] >> i) & 1;
            //这句可以换个法写,因为二进制上不是1就是0
            //if((arr[j]>>i)&1)
            //    bit[i]++;
		}
	}
//上面记录完毕后,来遍历比特位数组
	int tmp = 0;
	for (int i = 0; i < 32; i++) {
//当模k不等于0时,说明不是k的倍数,就是说没有重复的那个数字的这一位上是1
		if (bit[i] % k != 0)
//是比特位上第几位的1就还原几位得到十进制数,然后判断其他位
			tmp += 1 << i;
	}
//最后返回该数
	return tmp;
}

思路3:(排序法)

把这个数组按升序排序,因为只有一个不重复的数字 ,所以其他相同数字都是相邻的,所以判断一个数字跟两边数字是否相等就能 找出没有重复的数字,分为三种情况:

  1. 这个数字在数组头,只需要跟后面的一个数字比较就行
  2. 这个数字在数组尾,只需要跟前面的一个数字比较就行
  3. 这个数字在数组中间,就需要跟前后两个数字都要比较了

思路4:(异或方法)

按位异或可以非常快速的查找出数组中不是重复的数字,因为相同数字异或为0,0与任何数字异或都为任何数字本身。

但是这种方法只限于当k为偶数时,也就是说重复出现次数为偶次数。


关于位运算操作符的用法:

 记C语言 &,|,^,>>,<<用法

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多低调

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值