拓展 欧几里得算法 求逆元_程序员经典算法面试题,从大数据中找出唯一出现一次或两次的数!...

本文来讲两道关于从大数据中找唯一出现一次或两次的数。

08d5fb92a2ad819db983bf7cd0693ac0.png

题目分别如下

1.给定一个长度为1000001的整数数组,没有排过序,所有整数的范围均在int内,除了其中一个数字出现过1次以外,其余的数字都出现过2次,找出这个唯一出现1次的数字。

因为异或操作有一个性质:相同两个数异或结果为零,零和任何数的异或结果为任何数。即a^a=0,0^a=a,那么所有出现两次的数异或起来得到的结果为零,将这个零再与唯一出现一次的数进行异或,就得到了那个数了,在这里异或操作满足交换律。

b45264f663a265a6fe4567d075de96ff.png

所以只需要将这1000001个数字异或起来就得到那个唯一出现1次的数字了。代码如下

int solve(int a[], int n) { int ans = 0; for (int i = 0; i < n; i++) { ans ^= a[i]; } return ans;}

2.给定一个长度为1000001的整数数组,没有排过序,所有整数的范围均在int内,除了其中一个数字出现过2次以外,其余的数字都出现过3次,找出这个唯一出现2次的数字。

这道题就要比上面的题难一点了,首先有一个明显的性质:出现过三次的所有数字加起来一定能被3整除。我们如果把所有数字都写成三进制的形式,即如下

009f7df46b0b34d8674740a74344b407.png

一个数的三进制表示

那么将相同次幂的系数都加起来并且对3取余,其结果将和唯一出现过两次的数字的和对3取余一样,假如最终得到的系数为k0,k1,k2,...,km,那么对于其中某个ki,有

f17d2bdc23786bc070c1358e85022f15.png

我们需要求a_i的值,将上述式子变形得到如下结果

f207ff6f5801450223905689953c4d48.png

因为k_i是系数,所以k_i∈[0, 2],这里可通过扩展欧几里得算法解方程求出a_i。

d4e85cad935064ff894ceb8a4a1b8f0b.png

还可以通过用逆元公式求a_i,即算出2模3的逆元,得到

898facca5134cebd895339e366e4b3f9.png

即2模3的逆元为2,所以计算a_i的公式如下

053bdf7afe93d3daf5dc2b65afc52294.png

得到所有的a_i后,再转化为十进制就是我们要求的x的值了。代码如下

a58f2ef09ccb37452cad23458110ceb9.png

这两道题算是比较经典的面试题,掌握这些思想很重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值