问题描述
Given a sorted array consisting of only integers where every element appears twice except for one element which appears once. Find this single element that appears only once.
Example 1:
Input: [1,1,2,3,3,4,4,8,8]
Output: 2
Example 2:
Input: [3,3,7,7,10,11,11]
Output: 10
Note: Your solution should run in O(log n) time and O(1) space.
思路分析
给一已排序的数组,数组中除了一个元素,其余的元素都出现了两次,找到这个只出现了一次的元素。
首先想到的方法就是使用异或,因为一个数异或它自身为0,所以 O(n) 的时间就可以。
但是题目要求的是 O(logn) 的时间复杂度,只能使用二分查找的方式。在正常情况下,如果没有这个单独的元素出现,对于i % 2 == 0,nums[i] == nums[i + 1],我们可以利用这个条件进行二分搜索。计算中值,然后根据中值的位置判断要对比的元素。
代码
异或法
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int res = 0;
for (int i = 0; i < nums.size(); i++){
res ^= nums[i];
}
return res;
}
};
时间复杂度:
O(n)
空间复杂度:
O(1)
二分法
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int res = 0;
for (int i = 0; i < nums.size(); i++){
res ^= nums[i];
}
return res;
}
};
时间复杂度:
O(logn)
空间复杂度:
O(1)
反思
还有更直接的,将left和right的值设置称为点对的索引,从第0对到第n/2对,每次要乘2才能使用,nums[2 * mid] == nums[2 * mid + 1],这样会更加直观。
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int mid = 0, left = 0, right = nums.size() / 2;
while (left < right){
mid = left + (right - left) / 2;
if (nums[2 * mid] == nums[2 * mid + 1])
left = mid + 1;
else
right = mid;
}
return nums[2 * left];
}
};