Table of contents
Given problem
You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once.
Return the single element that appears only once.
Your solution must run in O(log n) time and O(1) space.
Example 1:
- Input: nums =
[1,1,2,3,3,4,4,8,8] - Output: 2
Example 2:
- Input: nums =
[3,3,7,7,10,11,11] - Output: 10
Constraints:
1 <= nums.length <= 1050 <= nums[i] <= 105
Using XOR bitwise operator
When reading the problem statement, the property of elements is that each element appears twice. To take advantage of this property, we can use XOR bitwise operator for all elements. Just because applying two same elements with XOR operator will be 0.
To understand why we have this property, we need to look at the formulation:
- 1 + 1 = 0
- 0 + 0 = 0
- 0 + 1 = 1
- 1 + 0 = 1
For example: 3 = 1100 => 1100 + 1100 = 0000
To know more about the bitwise operations, we can look at the following article Bit manipulation.
Below is our source code:
class Solution {
public int singleNonDuplicate(int[] nums) {
int singleNum = 0;
for (int i : nums) {
singleNum ^= i;
}
return singleNum;
}
}
The complexity of this solution is:
- Time complexity:
O(n). - Space complexity:
O(1).
Using Binary Search algorithm
-
Analysis
Due to the sorted array, Binary Search can be applied in this case. We will choose the third invariant of Binary Search.
-
Our requirement is to find the element’s value that is repeated one time.
So we need to seek the conditions that relates to
midpointer in Binary Search algorithm.Below are the two cases that our value is satisfied the conditions of
midpointer.-
The
midwill be at the middle of the array.
In this case, the element with value
10is compared with its adjacent elements. So our result will be:int left = 0; int right = nums.length; ... int mid = left + (right - left) / 2; if (nums[mid] != nums[mid - 1] && nums[mid] != nums[mid + 1]) { return nums[mid]; } -
But we have another edge case. How about the element with value
10sit at the end of the array?
The
mid + 1will lead to the NullPointerException. So we will have the below segment code:if (nums[mid] != nums[mid - 1] && mid + 1 == nums.length) { return nums[mid]; }Why do we have these conditions?
Each element will be repeated twice. The
leftpointer always point to the last element that satisfies this condition. When themidpoints to last element of the array, it means that the remaining elements satisfied this condition.Therefore, the element at the
midposition will be need to check.
-
-
Which condition will we move the
right,leftpointers?Because the characteristic of this problem is that each element will be repeated twice. So it affects to the odd/even index of each element in the array.
-
If
midpoints to the odd index, we only need to compare the elements atmidandmid - 1positions.-
Case 1:

-
Case 2:

So we have:
int mid = left + (right - left) / 2; if (mid %2 != 0 && nums[mid] == nums[mid - 1]) { left = mid; } else { right = mid; } -
-
If
midpoints to the even index, we only need to compare the elements atmidandmid + 1positions.-
Case 1:

-
Case 2:

So we have:
int mid = left + (right - left) / 2; if (mid %2 == 0 && nums[mid] == nums[mid + 1]) { left = mid; } else { right = mid; } -
-
-
-
Solution
class Solution { public int singleNonDuplicate(int[] nums) { int left = 0; int right = nums.length; while (left + 1 < right) { int mid = left + (right - left) / 2; if (nums[mid] != nums[mid - 1] && (mid + 1 == nums.length || nums[mid] != nums[mid + 1])) { return nums[mid]; } else if ((mid % 2 == 0 && nums[mid] == nums[mid + 1]) || (mid % 2 != 0 && nums[mid] == nums[mid - 1])) { left = mid; } else { right = mid; } } return nums[left]; } }The complexity of this solution is:
- Time complexity:
O(logn). - Space complexity:
O(1).
- Time complexity:
Wrapping up
Refer: