class Solution:
def singleNonDuplicate(self, nums):
left, right = 0, len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if mid % 2 == 1:
mid -= 1
if nums[mid] == nums[mid + 1]:
left = mid + 2
else:
right = mid
return nums[left]
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (mid % 2 == 1) mid--;
if (nums[mid] == nums[mid + 1])
left = mid + 2;
else
right = mid;
}
return nums[left];
}
};
class Solution {
public int singleNonDuplicate(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (mid % 2 == 1) mid--;
if (nums[mid] == nums[mid + 1])
left = mid + 2;
else
right = mid;
}
return nums[left];
}
}
var singleNonDuplicate = function(nums) {
let left = 0, right = nums.length - 1;
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (mid % 2 === 1) mid--;
if (nums[mid] === nums[mid + 1]) {
left = mid + 2;
} else {
right = mid;
}
}
return nums[left];
};
nums
where every element appears exactly twice, except for one element which appears only once. Your task is to find and return the single element that appears only once. The solution must run in O(log n)
time and use O(1)
extra space.
nums
is an integer.O(log n)
hints that a binary search or other divide-and-conquer method is necessary.
Since the array is sorted and all elements except one appear in pairs, we can leverage the properties of indices and the structure of the data. The main realization is that before the single element, pairs start at even indices, and after the single element, pairs start at odd indices. This pattern lets us repeatedly halve the search space.
The brute-force approach (linear scan or XOR) is too slow or not allowed due to constraints. Instead, we focus on how to apply binary search effectively.
left
to 0 and right
to the last index of nums
.
left < right
, do the following:
mid
as the midpoint between left
and right
.mid
is odd, decrement it by 1. This ensures mid
always points to the first element in a pair.nums[mid]
and nums[mid + 1]
:
mid + 1
(since all pairs before the unique element are correct). Set left = mid + 2
.mid
or to its left. Set right = mid
.left == right
, the single element is at index left
.
nums = [1,1,2,3,3,4,4,8,8]
.
left = 0
, right = 8
mid = (0+8)//2 = 4
. Since 4 is even, we check nums[4] == nums[5]
(3 == 4)? No.
right = 4
.left = 0
, right = 4
, mid = 2
. nums[2] == nums[3]
(2 == 3)? No.
right = 2
.left = 0
, right = 2
, mid = 1
(odd, so mid = 0
). nums[0] == nums[1]
(1 == 1)? Yes.
left = 2
.left = 2
, right = 2
. Loop ends. The answer is nums[2] = 2
.2
is found efficiently.
O(n)
time and O(1)
space (if using XOR), or O(n)
space if using a hash map.
O(log n)
. Only a few variables are used, so space complexity is O(1)
.
O(log n)
time and O(1)
space. This approach is both elegant and optimal for the problem's constraints.