给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
解法一:
使用异或运算符
异或的特点 当 a、b 两个值不相同,则异或为 1 。当 a、b 两个值相同,异或为 0
例如 输入: var z=1 ^ 9 ^ 5 ^ 6 ^ 9 ^ 1 ^ 5 , 输出: 6
var singleNumber = function(nums) {
var x
for(var i=0;i<nums.length;i++){
x^=nums[i]
}
return x;
};
16 / 16 个通过测试用例
执行用时:88 ms
解法二:
对数组顺序排序,然后找到索引 i 不等于 i + 1 也不等于 i - 1 的元素返回
// 2018/11/21 晚上
var singleNumber = function(nums) {
nums=nums.sort(sortName)
for(var i=0;i<nums.length;i++){
if(nums[i]!=nums[i+1] && nums[i]!=nums[i-1]){
return nums[i]
}
}
};
var sortName=function(a,b){return a-b}
16 / 16 个通过测试用例
执行用时:112 ms
解法三:
对数组排序然后使用二分查找,
因为题目给的数据有个特点, “其它每个元素均出现两次” ,那么出现一次的数据一定会打乱偶数等于偶数+1的规律。
例如 [0,0,1,1,3,2,2],
然后利用这个规律找到索引 i 不等于 i + 1 也不等于 i - 1 的数字
var singleNumber = function(nums) {
nums=nums.sort(sortName)
var lo=0;hi=nums.length-1
while(lo<=hi){
mid=Math.ceil((lo+hi)/2)
if(nums[mid]!=nums[mid-1] && nums[mid]!=nums[mid+1]) return nums[mid]
if(mid%2==0) mid=mid+1
if(nums[mid]==nums[mid-1]){
lo=mid+1
}else{
hi=mid-1
}
}
};
var sortName=function(a,b){return a-b}
16 / 16 个通过测试用例
执行用时:248 ms