给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1] 输出: 1
示例 2:
输入: [4,1,2,1,2] 输出: 4
题解:
- 使用集合
用一个集合帮助存储,遍历数组,如果集合中存在该元素,则取出来,如果不存在则存进去。出现两次的元素会先存进去再取出来,只有出现一次的元素会存进去,因此最终集合中剩下的元素就是只出现一次的元素。
var singleNumber = function (nums) {
var numberSet = new Set();
for (var i = 0; i < nums.length; i++) {
if (numberSet.has(nums[i])) {
numberSet.delete(nums[i]);
} else {
numberSet.add(nums[i]);
}
}
return numberSet.values().next().value;
};
- 使用字典
使用一个dict来记录每个数字出现的次数,最后找到只出现一次的数字
var singleNumber = function (nums) {
var numberObj = {};
for (var i = 0; i < nums.length; i++) {
numberObj[nums[i]] = numberObj[nums[i]] ? numberObj[nums[i]] + 1 : 1;
}
return Object.entries(numberObj).find(([key, value]) => value === 1)[0];
};
- 集合 + 和
使用集合和存储数组中的数字,分别对集合和数组求和,由于只有一个元素出现了一次,因此数组的和将比集合的和的2倍小一点,小的正是只出现一次的数字。
var singleNumber = function (nums) {
var numberSet = new Set();
var arraySum = 0;
var setSum = 0;
for (var i = 0; i < nums.length; i++) {
numberSet.add(nums[i]);
arraySum += nums[i];
}
for (var num of numberSet) {
setSum += num;
}
return setSum * 2 - arraySum;
};
- 使用异或操作
- 任何数和0做异或都等于其本身,
a⊕0=a - 任何数和本身做异或都等于0,
a⊕a=0 - 异或运算满足交换律和结合律,
a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b
var singleNumber = function (nums) {
var result = 0;
for (var i = 0; i < nums.length; i++) {
result ^= nums[i];
}
return result;
};