题目
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:
Input: [1,1,2,3,3,4,4,8,8]
Output: 2Input: [3,3,7,7,10,11,11]
Output: 10
Note: Your solution should run in O(log n) time and O(1) space.
思考
最简单的方法是把数组遍历一遍(n/2即可)就能找到答案,可是不能满足O(log n)的复杂度。
看到O(log n)的复杂度,很容易想到二分查找,可是这不是传统的二分查找,不能通过直接比较中间数值与标准数值来决定答案在哪一半。
由于只有一个只出现一次的数,也就是说别的数都是成对出现的,所以我们需要的数的下标是偶数(第一个数的下标为0)。因此,我们可以根据这个标准来判断答案是在左半边还是右半边。
例子分析如下:
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8
输入:[1, 1, 2, 3, 3, 4, 4, 8, 8]
- 取中位数,即下标为4的3。如果中位数的下标为奇数,可以取其前一个数;
- 对比下标为4的3与下标为5的4,发现不相等,说明答案下标范围为[0,4];下标为4的3也可能为答案
- 取0和4的平均数,即下标为2的2;
- 对比下标为2的2与下标的3的3,发现不相等,说明答案下标范围为[0, 2];
- 取0和2的平均数,即下标为0的1;
- 对比下标为0的1与下标为1的1,相等,说明答案下标范围为[2,4];可以直接跳过下标为1的1,因为答案一定为第偶数个
- 2和4的平均数为3,因此取下标为2的2;
- 对比下标为2的2和下标为3的3,不相等,答案范围[2, 2];
- 2 == 2,答案为2。
答案
c++
只需要将二分查找的判定条件改变一下即可。
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
return binarySearch(nums, 0, nums.size() - 1);
}
int binarySearch(vector<int>& nums, int low, int high) {
if (low >= high) return nums[low]; //
int mid = (low + high) / 2;
if (mid % 2 != 0) {
mid--;
}
if (nums[mid] != nums[mid+1]) { // result is smaller than nums[mid+1], left
return binarySearch(nums, low, mid);
}
return binarySearch(nums, mid+2, high); // result is larger than nums[mid+1], right
}
};