题目描述
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗?
示例1
输入: [2,2,1]
输出: 1
示例2
输入: [4,1,2,1,2]
输出: 4
题解
方法1:利用Set集合元素不重复
创建一个Set数组,将nums数组的元素一个一个的插入set,成插入说明不重复,插入不成功说明是重复的。
class Solution {
public int singleNumber(int[] nums) {
Set<Integer> set = new HashSet<Integer>();
for(int num : nums){
if(!set.add(num)){
set.remove(num);
}
}
return (int)set.toArray()[0];
}
}
方法2:数组先排序,再遍历
题目说明了一个数字出现了1次,其他数字都出现了2次,所以数组的长度一定是个奇数。每次比较两个,循环步长设为2,分析一下单独数字出现的情况。
先对数组进行排序,从index=0开始,比较相邻的元素值,循环步长设为2,如果出现nums[i]和nums[i+1]不相等,那么nums[i]是出现一次的数字;如果全都相等,那么最后一个是单独出现的数字。
class Solution {
public int singleNumber(int[] nums) {
Arrays.sort(nums);
for(int i=0; i<nums.length-1; i+=2){
if(nums[i] != nums[i+1]){
return nums[i];
}
}
return nums[nums.length-1];
}
}
方法3:利用位运算
题目强调只有一个数字出现了1次,其他数字都出现了2次。我们可以利用异或运算进行解题。
在计算机中异或运算拥有以下特征
0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
- 1 ^ 1 = 0
因此,我们可以推出以下结论
- 归零律:a ^ a = 0
- 恒等律:a ^ 0 = a
交换律:a ^ b ^ c = a ^ c ^ b
也就是说,一个数(转成二进制),自己异或自己是0;同时任何数异或0都得他本身。
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for (int num : nums) {
res = res ^ num;
}
return res;
}
}
甚至可以省略一个变量,直接用数组第一个元素。
class Solution {
public int singleNumber(int[] nums) {
for(int i=1; i<nums.length; i++){ //从下标=1开始
nums[0] ^ = nums[i];
}
return nums[0];
}
}
// End //