题目要求:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
解决方案:
一、哈希集(HashSet)
哈希集有个重要特性,其是不包含任何重复元素的无序集合。所以,对于此题可谓是相当适用的,毕竟我们要求的值就是唯一的。
故当我们向哈希集添加重复元素时,如果添加失败,则移除当前试图向哈希集添加的元素。
代码如下:
public static int SingleNumber(int[] nums)
{
HashSet<int> set = new HashSet<int>();
for (int i = 0; i < nums.Length; i++)
{
//该判断语句的整体作用是:如果当前数字(nums[i])已经在之前出现过,那么在哈希集实例(set)中移除当前数字
// Add 方法的作用是添加当前数字于哈希集中,如果当前数字和该集合(set)元素存在重复,则返回 False 。故在此采用了逻辑非操作符(!)
if (!set.Add(nums[i]))
set.Remove(nums[i]); ;
}
//因为每个重复元素最多存在两个,而重复元素的第一个添加后均被移除,而第二个均未添加成功,故此时哈希集只保留唯一且未重复的元素
// First*1 方法的作用是返回该序列的第一个元素
return set.First();
}
通过哈希集实现的代码虽然效率较为理想,但就空间占用方面并不完美(其实要不了多少内存,但当要进行操作得数组大到一定程度时,这种解决方案可能会和下面将介绍得方案形成较大差距)。
值得注意的是,哈希集实例的 First 方法是由 Enumerable 类提供的。其于微软开发者网络(Microsoft Developer Network,即常称的 MSDN)中的释义是:返回序列中的第一个元素。由于所求数唯一,故可以通过 First 方法返回哈希集中唯一的元素。并且此方法包含重载,另一个方法*2的释义为返回序列中满足指定条件的第一个元素。
二、按位异或(xor)操作符
代码如下:
public static int SingleNumber(int[] nums)
{
//注意,这里为0而不是其它值得原因并不是盲目的:甲 按位异或 0 得 甲,甲 按位异或 甲 得 0
int result = 0;
for (int i = 0; i < nums.Length; i++)
{
// ^ 为C#提供的按位异或操作符,而 ^= 相似 += ,其效果等价于 result = result ^ nums[i]
result ^= nums[i];
}
return result;
}