给定条件,找到数组中只出现一次的数字
要求:
1.非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
2.算法具有线性时间复杂度。
3.不使用额外的空间。
输入:[1,1,3,4,4,5,5]
输出:3
输入:[2,2,1]
输出:1
- 方法一
要求中除了一个数出现了一次,其他数字都出现了2次。便可以考虑使用异或运算的特点来解决。
异或运算(^)是以二进制数据为基础进行运算的。
当代码中使用到异或运算时,都会先将两个数据进行转换,转换成二进制数据后,再进行运算。
异或中同位如果值相同(都是0或者都是1)则为0,不同(一个是0,一个是1)为1。
其运算规律是:两个操作数的位中,相同则结果为0,不同则结果为1。
a^a=0;自己和自己异或等于0
a^0=a;任何数字和0异或还等于他自己
a^b^c=a^c^b;异或运算具有交换律
另外,注意到一点,0与x异或都为x。我们便可以写出代码。
#Java
public int singleNumber(int nums[]) {
int result = 0;
for (int i = 0; i < nums.length; i++)
result ^= nums[i];
return result;
}
- 方法二(使用额外空间)
1.使用集合解决。
遍历数组中的元素,一个个添加到HashSet中,如果添加失败,说明以前添加过,就移除掉该元素。当我们把数组中的所有元素都遍历完的时候,HashSet中只会有一个元素,这个就是我们要求的值。
#Java
public int singleNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
if (!set.add(num)) {
//添加失败,说明这个值在集合Set中存在,则移除
set.remove(num);
}
}
return (int) set.toArray()[0];
}
2.使用哈希表存储每个数字和该数字出现的次数。遍历数组即可得到每个数字出现的次数,并更新哈希表,最后遍历哈希表,得到只出现一次的数字。
#Java
public int singleNumber(int[] nums) {
Map<Integer, Integer> countMap = new HashMap<>();
for(int num:nums){
int count = countMap.getOrDefault(num, 0) + 1;
countMap.put(num,count);
}
for(int num:nums){
if(countMap.get(num)==1){
return num;
}
}
return 0;
}
3.使用集合存储数组中出现的所有数字,并计算数组中的元素之和。由于集合保证元素无重复,因此计算集合中的所有元素之和的两倍,即为每个元素出现两次的情况下的元素之和。由于数组中只有一个元素出现一次,其余元素都出现两次,因此用集合中的元素之和的两倍减去数组中的元素之和,剩下的数就是数组中只出现一次的数字。
#python
def singleNumber(self, nums: List[int]) -> int:
result1 = 0
for num in nums:
result1+=num
result2 = 0
x = set(nums)
for num in x:
result2+=num
return result2*2-result1