需求
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
示例 1 :
输入:nums = [2,2,1]
输出:1
示例 2 :
输入:nums = [4,1,2,1,2]
输出:4
示例 3 :
输入:nums = [1]
输出:1
提示:
1 <= nums.length <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
除了某个元素只出现一次以外,其余每个元素均出现两次。
版本1
鄙人先想到的方法是. 定义一个 set 集合, 然后遍历数组, 判断数组中的元素是否存在于 set 中, 如果存在则删除掉, 不存在则放进去. 这样遍历完数组后, set 中就剩下唯一的那个元素了.
public int singleNumber(int[] nums) {
int length = nums.length;
Set<Integer> set = new HashSet(length);
int temp;
for( int i = 0; i < length; i++ ){
temp = nums[i];
if( set.contains(temp) ){
//删除掉
set.remove(temp);
}else{
set.add(temp);
}
}
// 返回set里的唯一的元素
return set.iterator().next();
}
运行后, 这个时间很恼火啊~~
版本2
看提示 1 <= nums.length <= 3 * 104
, 数组的长度可以为1. 当数组的长度为1的时候直接返回数组中的唯一元素就OK了.
public int singleNumber(int[] nums) {
int length = nums.length;
if( length == 1 ){
return nums[0];
}
Set<Integer> set = new HashSet(length);
int temp;
for( int i = 0; i < length; i++ ){
temp = nums[i];
if( set.contains(temp) ){
//删除掉
set.remove(temp);
}else{
set.add(temp);
}
}
// 返回set里的唯一的元素
return set.iterator().next();
}
时间提升了 2 秒~~
版本3 上异或
了解过异或的都知道哈, 疑惑运算符的显著特点就是 :
a ^ a = 0;
0 ^ b = b;
看到这里, 读者应该能恍然大悟了吧:
public int singleNumber(int[] nums) {
int length = nums.length;
if( length == 1 ){
return nums[0];
}
int unique = 0;
for (int num : nums) {
unique = unique ^ num;
}
return unique;
}
这耗时, 还有谁 ???
结尾
以上 是我对只出现一次的数字的一些遐想和延伸, 可能不是最优解, 但是算法的优化嘛 本身就是一个思索的过程, 能在这个思索和迭代的过程中有所收获和乐趣就是在成长了, 欢迎大家一起来交流更多的解答…