这道题目跟Single Number II比较类似,区别只是这道题目每个元素出现两次,而不是三次。我们仍然可以按照Single Number II中的两种方法来,都只是把取余3改成取余2即可。我们就列举一下第二种方法的代码如下:
public int singleNumber(int[] A) { int[] digits = new int[32]; for(int i=0;i<32;i++) { for(int j=0;j<A.length;j++) { digits[i] += (A[j]>>i)&1; } } int res = 0; for(int i=0;i<32;i++) { res += (digits[i]%2)<<i; } return res; }上面方法的时间复杂度仍然是O(n),空间是一个32个元素的数组,是O(1)的复杂度。
按照上面的方法,虽然空间复杂度是O(1)的,不过还是需要一个32个元素的数组。还有另一种方法是利用每个元素出现两次,以及位操作异或的性质来解决这个问题。因为两个相同的元素异或结果是0,利用这个特点我们可以对所有数组元素进行异或,如果出现两次的元素就会自行抵消,而最终剩下的元素则是出现一次的元素。这个方法只需要一次扫描,即O(n)的时间复杂度,而空间上也不需要任何额外变量,比起上面的方法更优。代码如下:
public int singleNumber(int[] A) { if(A==null || A.length==0) return 0; int res = A[0]; for(int i=1;i<A.length;i++) { res ^= A[i]; } return res; }上面的方法实现非常简练,不过也相当取巧,可能没有准备过比较难在面试中想到。相对而言第一种方法是比较通用的,无论出现多少次都是适用的。第二种方法属于对于出现两次这种特殊情况才能使用,不过方法巧妙,有点体现位运算的精髓,所以个人还是挺喜欢的哈。
没有评论:
发表评论