1. 题目
给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。
示例 1:
输入: [1,1,2,3,3,4,4,8,8]
输出: 2
示例 2:
输入: [3,3,7,7,10,11,11]
输出: 10
注意: 您的方案应该在 O(log n) 时间复杂度 和 O(1)空间复杂度中运行。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-element-in-a-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
2.1 O(n) 位运算解法
- 一个数与自己 异或^ 等0
- 0^n = n
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int ans = 0;
for(int i = 0; i < nums.size(); ++i)
ans ^= nums[i];
return ans;
}
};
2.2 递归查找
最坏O(n)时间复杂度
class Solution {
bool found = false;
int ans;
public:
int singleNonDuplicate(vector<int>& nums) {
if(nums.size()==1)
return nums[0];
find(nums,0,nums.size()-1);
return ans;
}
void find(vector<int>& nums, int l, int r)
{
if(found || l > r)
return;
int mid = l+((r-l)>>1);
if((mid == 0 && nums[mid] != nums[mid+1])
|| (mid == nums.size()-1 && nums[mid-1] != nums[mid]))
{
found = true;
ans = nums[mid];
}
else if(nums[mid] != nums[mid+1] && nums[mid] != nums[mid-1])
{
found = true;
ans = nums[mid];
}
else
{
find(nums,l,mid-1);
find(nums,mid+1,r);
}
}
};
2.3 二分查找
看见题目要求的时间复杂度是 O(lg n),且有序,应该很容易想到二分法
- 答案一定在切分的个数为奇数个的那一边
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int l = 0, r = nums.size()-1, mid;
while(l < r)
{
mid = l+((r-l)>>1);
if(mid % 2) //奇数,1,奇数
{
if(nums[mid] == nums[mid+1])
r = mid-1;
else
l = mid+1;
}
else // 偶数个,1,偶数个
{
if(nums[mid] == nums[mid+1])
l = mid+2;
else
r = mid;
}
}
return nums[l];
}
};