题目链接:https://leetcode-cn.com/problems/single-element-in-a-sorted-array/
给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。
示例 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)空间复杂度中运行。
解题思路:题目中已经说了使用O(log n)的时间复杂度,因此直接对数组进行排序然后再遍历的做法肯定是不可以的,因此最好用二分法来进行求解。在使用二分法进行求解就要关注该数组中位于中间的元素值的特点,以此来判断我们的答案是在中间,左边还是右边。
算法步骤:
(1)首先令low 和 high 分别指向数组首尾的两个元素,然后进行二分查找将搜索空间减半,直到找到单一元素或者仅剩一个元素为止。
(2)在进行中间元素判断时可发现如果 mid 为奇数且前半部分无单一元素的时有array[mid] = array[mid-1] (数组从0开始计数),因此不满足这种情况就表明单一元素在前半部分,可以令 high = mid -1; 否则表明单一元素在后半部分, 可以令 low= mid + 1;
(3)当 mid 为偶数且前半部分无单一元素时有array[mid] = array[mid + 1] , 因此不满足这种情况就表明单一元素在前半部分,可以令high = mid - 2 (此时 array[mid] = array[mid - 1]); 否则表明单一元素在后半部分,可以令 low = mid + 2;
class Solution {
public int singleNonDuplicate(int[] nums) {
if (nums.length < 0) return -1;
int low = 0;
int high = nums.length - 1;
while (low < high){
int mid = low + (high - low) / 2;
if (mid % 2 == 0){
if (nums[mid] == nums[mid - 1]){
high = mid - 2;
} else if (nums[mid] == nums[mid+1]){
low = mid + 2;
} else {
return nums[mid];
}
}else{
if (nums[mid] == nums[mid - 1]){
low = mid + 1;
} else if (nums[mid] == nums[mid + 1]){
high = mid - 1;
} else {
return nums[mid];
}
}
}
return nums[low];
}
}