您的位置:首页 > 移动开发 > 微信开发

算法题:从数组找数字(网易2017校园招聘) 2017-10-10 算法爱好者 (点击上方公众号,可快速关注) 给定一个数组,除了一个数出现 1 次之外,其余数都出现 3 次。找出出现一次的数。

2017-10-15 20:01 495 查看


算法题:从数组找数字(网易2017校园招聘)

给定一个数组,除了一个数出现 1 次之外,其余数都出现 3 次。找出出现一次的数。如:{1,
2, 1, 2, 1, 2, 7}, 找出 7。

格式:

第一行输入一个数n,代表数组的长度,接下来一行输入数组A
,(输入的数组必须满足问题描述的要求),最后输出只出现一次的数。

要求:

你的算法只能是线性时间的复杂度,并且不能使用额外的空间哦~

样例输入

4

0 0 0 5

样例输出

5

代码如下:

#include<iostream>

using namespace std;

int main()

{
int fx[10]={1,3,1,4,4,3,17,4,3,1};
int y1=0,y2=0;
for(int z=0;z<10;z++)
{
int x1=fx[z]&~y1&y2|~fx[z]&y1&~y2;
int x2=fx[z]&~y1&~y2|~fx[z]&~y1&y2;
y1=x1;
y2=x2;
}
cout<<y2<<endl;

}

原理是这样的,采用二进制的思想,仅仅有一个数出现一次,那么就意味着,把所有的数转换成二进制进行对应位累加,凡是得到的某些位的和不是3的倍数,即位3*n+1时,就一定时属于那个只出现一次的数,用位对应的权值进行累加即可。现在的问题是空间复杂度要求是O1的,那么用数组来存储二进制位并做权值累加就行不通了。但是换个思路,int本身就是32位的,是否可以不用数组而只用少许几个int变量呢,答案是肯定的。

首先,这些对应位累加后的结果要么是3*n,要么是3*n+1,因此我们可以只记录三个状态即可,到3即退回到0状态。因此引入两个变量y1,y2(两个二进制位可以表示四个数).

那么我们现在对数X,看作是XnXn-1.....X1,y1看作是y1ny1n-1.....y11,y2是y2ny2n-1...y2。

那么对于X,y1,y2的第n位,用y1,y2的第n位记录当前数据进行二进制累加时,该位的个数用y1y2的第n位所表示的二进制位的个数。

于是对于该位有如下表格:

由之前的推论可知,y1y2最终表示的数只有3和1,而因为对应位如果为3则不是我们需要求的元素,我们把y1y2的值模3,实际上y1,y2最后的状态就是00和01,那么很明显的,最后的结果全部落在y2上,所以y2的结果值就是需要求的元素。

现在只需要得到y1,y2每次的计算公式即可。对应于上述表格写出逻辑表达式即x1=fx[z]&~y1&y2|~fx[z]&y1&~y2;x2=fx[z]&~y1&~y2|~fx[z]&~y1&y2;(注:运算优先级~>&>|),得到结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐