Fork me on GitHub

LeetCode-136:只出现一次的数字

本题出现在LeetCode的136题

果然HashMap是万能的,而那些骚操作,就是想不来,来说说吧

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

1
2
输入: [2,2,1]
输出: 1

示例 2:

1
2
输入: [4,1,2,1,2]
输出: 4

自己的做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int singleNumber(int[] nums) {
HashMap<Integer,Integer> hashMap = new HashMap<>();

for (int i = 0;i<nums.length;i++){
if(!hashMap.containsKey(nums[i])){
hashMap.put(nums[i],1);
}else{
hashMap.put(nums[i],hashMap.get(nums[i])+1);
}
}
for(Integer key: hashMap.keySet()){
int count = hashMap.get(key);
if(count==1){
return key;
}
}
return -1;
}
}

人家的骚操作:

1
2
3
4
5
6
7
8
9
public static int singleNumber(int[] nums) {
int len=nums.length;
int temp=0;
for(int i=0;i<len;i++){
temp^=nums[i];
System.out.println("temp:"+temp);
}
return temp;
}

我们来说一下异或运算吧!!!

  异或是一种基于二进制的位运算,用符号 XOR 或者 ^ 表示,其运算法则是对运算符两侧数的每一个进制位同值则取0,异值则取1.

简单理解就是不进位加法,如

1
1+1=0,0+0=0,1+0=1.

For example:

3^5 = 6

转成二进制后就是  0011 ^ 0101   二号位和三号位都是异值取1 末尾两个1同值取零,所以3^5 = 0110 = 6

异或运算符的性质:

1、交换律

2、结合律(即(a ^ b)^c == a ^ ( b ^ c ))

3、==对于任何数x==,都有==x ^ x=0==,==x ^ 0=x==

4、==自反性== A XOR B XOR B = A xor 0 = A

  它最重要的性质还是自反性

A XOR B XOR B = A,

即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。

例如:

  所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达式 (值)

1
2
3
4
5
6
7
int a = 10,b = 5;

a = a ^ b;

b = a ^ b;

a = a ^ b;

这样就将两个数交换过来了。

我们来推导一下

1
2
3
4
5
a = a ^ b;

b = a ^ b = a ^ b ^ b = a(由第一步得到,因为a = a ^ b ,代换就行)

a = a ^ b = a ^ b ^ a(因为此时a = a ^ b 而b = a,代换即可)