给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
暴力算法
可以先统计出各个元素出现的次数,然后找到那个次数等于 1 的元素:
public int singleNumber(int[] nums) {
Map<Integer, Integer> countMap = countNum(nums);
for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
if (entry.getValue() == 1) {
return entry.getKey();
}
}
return -1;
}
private Map<Integer, Integer> countNum(int[] nums) {
Map<Integer, Integer> countMap = new HashMap<>();
for (int num : nums) {
if (!countMap.containsKey(num)) {
countMap.put(num, 1);
} else {
countMap.put(num, countMap.get(num) + 1);
}
}
return countMap;
}
暴力算法借助了额外的空间,如果不借助额外空间就需要借助特别操作!
或运算有两种情况的计算结果为 true:
情况1:一个为 treu,另一个为 false
情况2:两个都为 true
其中情况1也可以专门称为 异或运算,而异或运算就有个常见的用途:判断两个值是否不同!
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
异或运算有如下几个运算定律:
1)一个值与自身的运算,总是为 false x ^ x = 0
2)一个值与 0 的运算,总是等于其本身 x ^ 0 = x
3)可交换性 x ^ y = y ^ x
4)结合性 x ^ (y ^ z) = (x ^ y) ^ z
比如:
a ^ b ^ c ^ a ^ b
= a ^ a ^ b ^ b ^ c
= 0 ^ 0 ^ c
= c
public int singleNumber(int[] nums) {
int ans = nums[0];
if (nums.length > 1) {
for (int i = 1; i < nums.length; i++) {
ans = ans ^ nums[i];
}
}
return ans;
}