这道题也是LeetCode上的题目,但是我没能自己做出来。悲伤脸。。题目链接
题目限定的是给一个数组,里面的元素都是成对出现的,但是出了一个不是。
题目要求就是不使用额外的空间和线性的时间复杂度找出那个不成对的元素。
比如数组:arr = {1,1,2,2,3},我们要找到3这个元素并返回。
这道题目我想了好久,也没能找到满足题目要求的“不使用额外的空间”、“线性的时间复杂度”这两个要求。最终,我只能去研究别人的代码,发现大神们使用xor(异或)就完美解决了这个问题。
代码如下:
public class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int i=0;i<nums.length;i++) res^=nums[i];
return res;
}
}
这个代码十分简洁,但是里面的思想一般还真难想到—将数组元素进行连续的异或。
下面来分析下代码执行过程:
- 比如说传给方法的参数是{1,1,2,2,3}
- for循环当中的res^=nums[i]就等价于nums[0]^nums[1]^nums[2]^nums[3]^nums[4]
- 也就是:1^1^2^2^3
- 异或的运算结果就要考虑二进制了,将元素(1,2,3)转换成二进制进行异或运算
- 01^01^10^10^11,其中01^01=00,00^10=10,10^10=00,00^11=11
也就是累计异或运算后得到二进制结果是11,也就是3。
上面的计算可以得到下面几点:
- 任何数与0异或都得到其自身
- 任何数与自身异或都得到0
- 异或满足交换律
所以,在成对的元素中找出唯一不成对的那个,使用异或是最有效的手段。