Code Ganker: Single Number -- LeetCode

2014年3月30日星期日

Single Number -- LeetCode

原题链接: http://oj.leetcode.com/problems/single-number/
这道题目跟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;
}
上面的方法实现非常简练,不过也相当取巧,可能没有准备过比较难在面试中想到。相对而言第一种方法是比较通用的,无论出现多少次都是适用的。第二种方法属于对于出现两次这种特殊情况才能使用,不过方法巧妙,有点体现位运算的精髓,所以个人还是挺喜欢的哈。

没有评论:

发表评论