点击关注上方“图解面试算法”,
设为“置顶或星标”,一起刷 LeetCode。

作者:chilimyan
题目描述
示例 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)空间复杂度中运行。
题目解析
解法一:二分搜索
-
(1)3、3、4 -
(2)3、4、3 -
(3)4、3、3
动画理解
代码实现
class Solution {
public int singleNonDuplicate(int[] nums) {
int lo = 0;
int hi = nums.length - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
boolean halvesAreEven = (hi - mid) % 2 == 0;
if (nums[mid + 1] == nums[mid]) {
if (halvesAreEven) {
lo = mid + 2;
} else {
hi = mid - 1;
}
} else if (nums[mid - 1] == nums[mid]) {
if (halvesAreEven) {
hi = mid - 2;
} else {
lo = mid + 1;
}
} else {
return nums[mid];
}
}
return nums[lo];
}
}
复杂度分析
-
时间复杂度:O(log n),在每次循环迭代中,我们将搜索空间减少了一半。 -
空间复杂度:O(1),仅用了常数空间
解法二:仅对偶数索引进行二分搜索
mid = mid + 1 ,即解法一的第三种情况,因为mid右边个数为偶数,所以mid+2到hi个数为奇数,那么只出现一次的那个元素肯定在mid的右边,将lo移动到mid+2位置。
动画理解
代码实现
class Solution {
public int singleNonDuplicate(int[] nums) {
int lo = 0;
int hi = nums.length - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (mid % 2 == 1) mid--;
if (nums[mid] == nums[mid + 1]) {
lo = mid + 2;
} else {
hi = mid;
}
}
return nums[lo];
}
}
复杂度分析
-
时间复杂度:O(log2 / n)=O(log n),我们仅对元素的一半进行二分搜索。 -
空间复杂度:O(1),仅用了常数空间
今天是 『 365 刷题计划 』 第 32 天。每晚八点,一起图解一道算法题,不见不散!
欢迎关注我的公众号“图解面试算法”,如果喜欢,麻烦点一下“在看”,转发+在看相当于打赏!

本文分享自微信公众号 - 五分钟学算法(CXYxiaowu)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/4010368/blog/4382418