class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
/*r 初始化为 k,它表示可能的第一个异常配对索引的上界。
如果所有配对都正常,那么第一个异常配对并不存在,此时答案就是最后一个单独元素,
可以认为“虚拟”的异常索引为 k,对应位置为2k。
l 表示已知正常的配对索引的下界。它永远指向一个“正常”的配对(或者边界外)。
因为配对索引最小可能为 0,为了能包含 0,我们需要将左边界设在 -1。
这里采用开区间,l=-1 是一种经典写法,使得 (l, r)
始终包含所有可能的答案,且更新时直接 l = mid 或 r = mid 即可*/
int l = -1,r = nums.size() /2;
/*当 l + 1 == r 时,表示区间内没有整数元素(因为 l 和 r
是相邻整数),此时区间为空,停止循环。 否则,区间 (l, r)
至少包含一个整数,我们继续二分*/
while (l + 1 < r) {
int mid = l + (r - l) / 2;
(nums[mid * 2] != nums[mid * 2 + 1] ? r : l) = mid;
/*判断第 mid 对的两个元素是否相等。
如果不相等,说明第一个异常配对出现在 mid 或更左侧,因此将右边界 r 更新为 mid。
如果相等,说明第 mid 对正常,异常在右侧,因此将左边界 l 更新为 mid。*/
}
return nums[r * 2];
/*循环结束时,(l, r) 为空,即 l+1 == r。
此时 r 指向第一个异常配对的索引(如果存在),或者等于 k(全正常)。
答案元素的位置是 2*r:
如果 r 是异常配对索引,则 2*r 就是该对的第一个元素(即单独元素)。
如果 r == k,则 2*r = 2k,正好是最后一个元素,也是正确答案。*/
}
};