二分,又是二分。
这里借鉴一下宫水三叶大佬的题解吧。
由于给定数组有序 且 常规元素总是两两出现,因此在单一元素之前,我们有结论:成对元素中的第一个所对应的下标必然是偶数,成对元素中的第二个所对应的下标必然是奇数。而在单一元素之后,结论是相反的。
由此我们可以进行二分:
class Solution {
public int singleNonDuplicate(int[] nums) {
int n = nums.length;
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] == nums[mid ^ 1]) l = mid + 1;
else r = mid;
}
return nums[r];
}
}
关于异或:
像这道题这种 连续段 偶奇 两两成对 的组合,适合使用 异或 来找相应的成组对象。
实际上,该技巧广泛地应用在图论存图中:使用邻接表(链式向前星)存无向图时,直接访问 当前边 e e e 所对应的 反向边 e ′ e' e′。这也是为什么在 链式向前星 中我们只需要使用 单链表 并设定 i d x idx idx 从 0 0 0 开始进行存图即可:能够满足遍历所有出边,同时如果有访问相应反向边的需求,只需要通过 e[i^1] 访问即可。