题目描述
给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。
请你找出并返回只出现一次的那个数。
你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。
示例 1:
输入: nums = [1,1,2,3,3,4,4,8,8]
输出: 2
示例 2:
输入: nums = [3,3,7,7,10,11,11]
输出: 10
提示:
1 <= nums.length <= 1050 <= nums[i] <= 105
题目解释
解法1 暴力解决
空间复杂度为: O(n) > O(log n) 不符合题意
但实际执行时间好像跟解法2 差不多
/**
* @param {number[]} nums
* @return {number}
*/
var singleNonDuplicate = function(nums) {
let i = 0 ,tmp = nums[0];
for(var num of nums){
if(num != tmp){
if(i == 1){
return tmp;
}
tmp = num;
i = 1;
}else{
i++;
}
}
return tmp
};
解法2 二分法
因为每个元素都会出现两次,唯有一个数只会出现一次。
所以数组一定是奇数
按常规的方法要去查看中间元素与前一个元素一致 还是与后一个一致 这样相当于多比较了一次
这边用了异或
异或:如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
则:
0 ^ 1 = 1
1 ^ 1 = 0
2 ^ 1 = 0010 ^ 0001 = 0011 = 3
3 ^ 1 = 0011 ^ 0001 = 0010 = 2
4 ^ 1 = 0100 ^ 0001 = 0101 = 5
5 ^ 1 = 0101 ^ 0001 = 0100 = 4
在递增序列里,并且每个元素都会出现两次,则最理想的情况是 [0,1] [2,3] [4,5] ,这样就不用分别去与前后元素对比了。
如果在每队数据里,2个元素都相等,则单数出现在后面的数据里
否则单数出现在前面的数据里。
var singleNonDuplicate = function(nums) {
let low = 0,hight = nums.length - 1;
while(low < hight){
let mid = parseInt((hight + low)/2);
if(nums[mid] == nums[mid ^ 1]){
low = mid + 1
}else{
hight = mid
}
}
return nums[low];
};