Explanation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Consider the number: 
[1(0), 1(1), 2(2), 3(3), 3(4), 4(5), 4(6), 8(7), 8(8)]
    , number(index)

Here, the single number is 2, let's call it SN

Note that:
- For each duplicate pair that appears to the left 
  of SN, the first occurence appears at even index 
  and second occurence appears at odd index
- For each duplicate pair that appears to the right 
  of SN, the first occurence appears at odd index 
  and second occurence appears at even index

Now to easily detect weather we are to the left or
right of SN, we can employ XOR with 1 operator.

Property of XOR with 1 operator:

XOR_1(x) = x ^ 1 = x + 1   , when x is even
XOR_1(x) = x ^ 1 = x - 1   , when x is odd

From this knowledge, it can be infered that for each index i:

number[ i ]  = number[ XOR_1(i) ]  ,when i is to 
                                    left of SN 
number[ i ] != number[ XOR_1(i) ]  ,when i is at SN or to 
                                    the right of SN

For example, at i=1, i is to left of SN

number[i] = number[1] = 1 == number[ XOR_1(1) ] 
= number[ 1-1 ] = number[0] = 1

at i=2, i is at Single Number (SN)

number[2] = 2 != number[XOR_1(2)] = number[3] = 3

at i=6, i is to right of SN
number[6] = 4 != number[XOR_1(6)] = number[7] = 8

You can verify this for any i

Now our job is to find the minimum valud of i such that
number[i] != number[XOR_1(i)]

This can be done using binary search.

It is worth mentioning that at i=8 in the above example
number[ XOR_1(8) ] = number[ 9 ] which is out of bonds

We avoid this situation by using ( i < j ) as loop 
condition. Which implies that i will never reach the 
end to make mid = 9

The binary search is designed such that j always takes
valid values, where valid means nums[j] != nums[j^1]

When i == j, we are at the leftmost valid index, which
is exactly what we require

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function singleNonDuplicate(nums: number[]): number {
    const N = nums.length;

    let i = 0, j = N-1;

    while ( i < j ) {
        const mid = i + Math.floor( (j-i) / 2 );

        if ( nums[mid] != nums[mid^1] )
            j = mid;
        else
            i = mid + 1;
    }

    return nums[j];
};