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;elsel = mid+1;} else // 偶数个,1,偶数个{if(nums[mid] == nums[mid+1])l = mid+2;elser = mid;}}return nums[l];}
};