题目描述:
给定一个非空数组,除了某个元素只出现一次之外,其余每个元素都出现了三次,要求不使用额外的空间找出那个只出现一次的数。
题解:
将每个数字看做0,1组成的二进制序列,为了方便讨论,我们把每个数拆分为独立的二进制考虑。此时元素出现的次数为1次和3次,用一个状态位只能表示一个元素出现一次或者0次,
我们用两个状态位来描述模3的状态转移过程:00->01->10->00。状态转移过程如下:
有了状态转移方程之后,结合卡诺图就可以求出a,b的表达式了。下图为关于b的卡诺图:
状态方程为。
那么最终的结果是什么呢?前面我们把一个数字拆分位独立的二进制位来进行讨论,对于一个数字X而言,a,b不再是单个的状态位,而是长度与X的二进制长度一样的数字。
题目要求的数字为只出现一次的数字,对于单个状态位而言,符合题意的是a = 0,b=1情况的数字。也就是说对于每一位(二进制表示)而言,只出现一次的数X在该位为1的时候,
b在该位值为1,就是说b为最终的结果。
AC代码:
int singleNumber(vector<int>& nums) { int a = 0, b = 0; int tmp; for (auto x : nums) { tmp = b; b = (b ^ x) & ~a; a = (x & tmp) | (~x & a); } return b; }