题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1] 输出: 1
示例 2:
输入: [4,1,2,1,2] 输出: 4
本题属于简单题,思路有两个:
第一个思路:查找表map,我首先想到的是用map,存储数组元素和出现的次数,然后遍历map,判断如果键对应的值为1,则将该键输出。
第二种思路:异或运算符。这个真的是一个非常好的方法,我没有想到,借鉴leetcode评论中的思路。太巧妙了,因为异或运算符有几个特性: 1>满足 交换律:a ^ b ^ c <=> a ^ c ^ b
2>任何数与0异或为任何数 0 ^ n => n
3>相同的数异或为0: n ^ n => 0
有了这几个特性,这个题特别太容易求解,因为题目说,数组中只有一个数是出现一次其余全是两次,这样两次的异或后全为0,0在于出现一次的异或,全为本身,最后输出这个出现一次的即可。
代码如下:
第一种思路:
// 第一种方法用查找表来存储元素和出现的次数,当次数为1时则返回这个元素。
Map<Integer,Integer> map =new HashMap <> ( );
for (int i=0;i<a.length;i++){
if (map.containsKey ( a[i] )){
map.put ( a[i],map.get ( a[i] )+1 );
}else {
map.put ( a[i],1 );
}
}
for (int num:map.keySet ()){
if (map.get ( num )==1){
System.out.println(num);
}
}
执行结果:
执行用时:
第二种方法:
//借鉴评论里的方法,根本没有想到这道题使用异或运算符,很忽视啊。
// 交换律:a ^ b ^ c <=> a ^ c ^ b
//
// 任何数于0异或为任何数 0 ^ n => n
//
// 相同的数异或为0: n ^ n => 0
int result=0;
for (int i=0;i<a.length;i++){
result^=a[i];
}
System.out.println(result);
执行用时:
总结:这道题用异或运算特变简便,代码特别少,时间复杂度特别低。以前学习真没重视这么重要,强大的东西。这就证明了一点,那些越不重视的东西,在某些时候还是最重要的。永远啊不要轻视那些看似没用的东西。
2019-4-2