LeetCode | Single Number

Given an array of integers, every element appears twice except for one. Find that single one.

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

题目:给定数组中除了一个特例只出现一次外,其他均出现两次

最基础的两重for循环算法:

//逻辑也是对的,但是为N方算法,提示Time Limit Exceeded,题目要求线性时间
public class Solution {
    public int singleNumber(int[] A) {
        if(A.length == 0) return -1;
        if(A.length == 1) return A[0];
                                             
        int result = -1;
        for(int i=0; i<A.length; i++){        
            int count = 1;
            for(int j=0; j<A.length; j++){  //对A[i]从A[0]开始试,用count计数A[i]在数组中出现的次数
                if(A[j]==A[i]){             //注意:此处不能从j=i+1开始向后找,逻辑错误
                    if(i==j){ continue; }   //自身相等,不算,continue对于if没影响
                    else{ count++; }
                }
            }
            if(count!=2){        //如果不是2,就是要找的
                result = A[i];   //break对if是没有影响的,用来跳出for循环
                break;
            }
        }
        return result;
    }
}

利用xor,线性时间复杂度,且无需额外内存的算法:

利用异或XOR来实现,xor的三个特性:【注意对int型的xor运算是位运算,是转换为二进制进行逐位异或求解的】
(1)a^b=b^a (2)a^a=0 (3)a^0=a
从上面三个个特性有:a^b^a = b^a^a = b^0 =b
继续向下推理:N个数进行异或,其顺序是无关的,可以任意变换,而只要其中有两个数相同,就能改变次序形成a^a=0,又b^0=b,那么这两个相同的数对最终的异或结果没影响
此题说数组中只有一个数字出现一此,其他都出现两次,则必有:A[0]^A[1]^A[2]^...^A[N]=result

(不仅仅是出现两次,只要是满足出现偶数次,然后找例外出现奇数次都能用异或位运算来找到)

public class Solution {
    public int singleNumber(int[] A) {
        for(int i=A.length-1; i>0; i--)
            A[i-1] ^= A[i];      //实际的效果就是在A[0]处进行所有数组元素的异或运算
        return A[0];
    }
}

扩展:求int[] A的sum
for(int i=A.length-1; i>0; i--)
    A[i-1] += A[i];

return A[0];


利用Java容器类Map<key, value>实现的O(2N)算法:

//Map<key,value> = Map<A[i],count>
//利用map来统计数组中各元素出现的次数,只须遍历一次数组就能统计完毕,在利用iterator迭代map找到result
//算法为O(N)+O(N),符合题目要求的线性时间复杂度,只不过需要额外内存
public class Solution {
    public int singleNumber(int[] A) {
        int result = 0;
        Map<Integer,Integer> hashMap = new HashMap<Integer,Integer>();
        for(int i=0; i<A.length; i++){
            if(hashMap.containsKey(A[i])){
                hashMap.put(A[i],hashMap.get(A[i])+1);
            }else{
                hashMap.put(A[i],1);
            }
        }
        
        Iterator<Map.Entry<Integer,Integer>> iterator = hashMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<Integer,Integer> entry = iterator.next();
            if(entry.getValue()!=2){
                result = entry.getKey();
                break;
            }
        }
        
        return result;
    }
}





原文地址:https://www.cnblogs.com/dosmile/p/6444463.html