题目描述
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.
Note: Your solution should run in O(log n) time and O(1) space.
例子
Input: [1,1,2,3,3,4,4,8,8]
Output: 2Input: [3,3,7,7,10,11,11]
Output: 10
思路
给定一个排好序的序列,找出只出现一次的那个数。
首先这个序列的个数肯定是奇数的,再由O(logn)时间复杂度可以很容易想到用二分查找的方法去实现。而如何判断元素只出现一次呢,只需要将其与它前后的元素相比较,若有相同的,则不是;若都不相同,则该元素为结果。
实现过程:
找到中间元素,然后我们需要判断只出现一次的元素在中间元素的左边还是右边。
判断方法:
1.前后子序列长度为奇数时
如果中间点和它前面一个元素相同,除去这两个点后前面的子序列长度就是偶数了,肯定没有目标元素了,所以目标元素就在右边的子序列中。如果与后一个元素相同,则在左边。
2.前后子序列长度为偶数时
如果中间点和它前面一个元素相同,除去这两个点后前面的子序列长度就是奇数了,肯定有目标元素,所以目标元素就在左边的子序列中。如果与后一个元素相同,则在右边。
终止条件
首尾下标相同(l == r),即只剩下一个元素。
代码
#include <iostream>
#include <vector>
using namespace std;
int cut(vector<int>& nums, int l, int r) {
if (l == r) return nums[l];
int n = (l+r)/2;
if ((l+n)%2 == 1) {
if (nums[n] == nums[n-1]) cut(nums, n+1, r);
else if (nums[n] == nums[n+1]) cut(nums, l, n-1);
else return nums[n];
} else {
if (nums[n] == nums[n+1]) cut(nums, n+2, r);
else if (nums[n] == nums[n-1]) cut(nums, l, n-2);
else return nums[n];
}
}
int singleNonDuplicate(vector<int>& nums) {
return cut(nums, 0, nums.size()-1);
}
int main() {
int a[7] = {3,3,7,7,10,11,11};
std::vector<int> v(a, a+7);
int result = singleNonDuplicate(v);
cout << result << endl;
return 0;
}
复杂度
时间复杂度:O(log n);
空间复杂度:O(1) .