540. 有序数组中的单一元素题解
题目来源:540. 有序数组中的单一元素
2022.02.14 题解
首先祝大家情人节快乐♥,有对象的祝99 .没有对象的祝转角遇到爱,嘿嘿
本题目是要求在有序数组之中找到只出现一次的数字是什么,但是附带了额外的要求就是时间复杂度要求是 O ( l o g n ) O(logn) O(logn),空间复杂度是 O ( 1 ) O(1) O(1)
首先脑海之中第一个想法就是遍历数组,找到只出现一次的数字,但是这种方式的时间复杂度是 O ( n ) O(n) O(n)大于要求的 O ( l o g n ) O(logn) O(logn),所以直接遍历的方式是行不通的。
那我们就换一种思考方式,时间复杂度是 O ( l o g n ) O(logn) O(logn),这个时间复杂度,用二分的查找方法刚刚好。
接下来就思考思考,用二分法查找,如何判断这个数字是不是重复的,根据题意,除了需要查找的数字,其余的数字均会出现 2 次,因此,要查找的的数字左右必然也是偶数,将数字排列开,会发现,要查询的数字的左侧的所有数字的下标都是一次偶数,一次奇数,而要查询数字的右侧所有的下标都是一次奇数,一次偶数,因此只需要判断两个相同数字的次序就能不断缩小查找范围,
就以左侧为例,如果 mid 是奇数,就判断 nums[mid] 与 nums[mid - 1] 是否相等
如果如果 mid 是偶数,就判断 nums[mid] 与 nums[mid + 1] 是否相等
同时还可以使用异或来进行判断,令 mid 与 1 进行异或操作就可以进行判断。
具体代码以及注释如下:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
// 将两个变量作为两个边界
int l = 0, r = nums.size() - 1;
// 开始进行查找循环
while (l < r) {
// 查找 mid
int mid = (r - l) / 2 + l;
// 判断 nums[mid] 是否在要查找的数字的左侧
if (nums[mid] == nums[mid ^ 1]) {
// 如果是就改变左边界
l = mid + 1;
} else {
// 如果不是,就改变右边界
r = mid;
}
}
// 返回答案
return nums[l];
}
};
class Solution {
public int singleNonDuplicate(int[] nums) {
// 将两个变量作为两个边界
int l = 0, r = nums.length - 1;
// 开始进行查找循环
while (l < r) {
// 查找 mid
int mid = (r - l) / 2 + l;
// 判断 nums[mid] 是否在要查找的数字的左侧
if (nums[mid] == nums[mid ^ 1]) {
// 如果是就改变左边界
l = mid + 1;
} else {
// 如果不是,就改变右边界
r = mid;
}
}
// 返回答案
return nums[l];
}
}