Given a sorted array in which all elements appear twice (one after one) and one element appears only once. Find that element in O(log n) complexity.
Example:
Input: arr[] = {1, 1, 3, 3, 4, 5, 5, 7, 7, 8, 8}
Output: 4
Input: arr[] = {1, 1, 3, 3, 4, 4, 5, 5, 7, 7, 8}
Output: 8
A Simple Solution is to traverse the array from left to right. Since the array is sorted, we can easily figure out the required element.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
void search( int arr[], int n)
{
int ans = -1;
for ( int i = 0; i < n; i += 2) {
if (arr[i] != arr[i + 1]) {
ans = arr[i];
break ;
}
}
if (arr[n - 2] != arr[n - 1])
ans = arr[n-1];
cout << "The required element is " << ans << "\n" ;
}
int main()
{
int arr[] = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = sizeof (arr) / sizeof (arr[0]);
search(arr, len);
return 0;
}
|
Java
import java.io.*;
class GFG {
static void search( int arr[], int n)
{
int ans = - 1 ;
for ( int i = 0 ; i < n- 1 ; i += 2 ) {
if (arr[i] != arr[i + 1 ]) {
ans = arr[i];
break ;
}
}
if (arr[n - 2 ] != arr[n - 1 ])
ans = arr[n- 1 ];
System.out.println( "The required element is "
+ ans);
}
public static void main(String[] args)
{
int arr[] = { 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 };
int len = arr.length;
search(arr, len);
}
}
|
Python3
def search(arr, n):
ans = - 1
for i in range ( 0 , n, 2 ):
if (arr[i] ! = arr[i + 1 ]):
ans = arr[i]
break
if (arr[n - 2 ] ! = arr[n - 1 ]):
ans = arr[n - 1 ]
print ( "The required element is" , ans)
arr = [ 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 ]
Len = len (arr)
search(arr, Len )
|
C#
using System;
class GFG {
static void search( int [] arr, int n)
{
int ans = -1;
for ( int i = 0; i < n; i += 2) {
if (arr[i] != arr[i + 1]) {
ans = arr[i];
break ;
}
}
if (arr[n - 2] != arr[n - 1])
ans = arr[n-1];
Console.Write( "The required element is "
+ ans);
}
public static void Main(String[] args)
{
int [] arr = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = arr.Length;
search(arr, len);
}
}
|
Javascript
<script>
function search(arr, n)
{
let ans = -1;
for (let i = 0; i < n; i += 2) {
if (arr[i] != arr[i + 1]) {
ans = arr[i];
break ;
}
}
if (arr[n - 2] != arr[n - 1])
ans = arr[n-1];
document.write( "The required element is " + ans + "<br>" );
}
let arr = [ 1, 1, 2, 4, 4, 5, 5, 6, 6 ];
let len = arr.length;
search(arr, len);
</script>
|
OutputThe required element is 2
Time Complexity: O(n)
Auxiliary Space: O(1), since no extra space has been taken.
Another Simple Solution is to use the properties of XOR (a ^ a = 0 & a ^ 0 = a). The idea is to find the XOR of the complete array. The XOR of the array is the required answer.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
void search( int arr[], int n)
{
int XOR = 0;
for ( int i = 0; i < n; i++) {
XOR = XOR ^ arr[i];
}
cout << "The required element is " << XOR << "\n" ;
}
int main()
{
int arr[] = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = sizeof (arr) / sizeof (arr[0]);
search(arr, len);
return 0;
}
|
Java
import java.io.*;
class GFG {
static void search( int arr[], int n)
{
int XOR = 0 ;
for ( int i = 0 ; i < n; i++) {
XOR = XOR ^ arr[i];
}
System.out.println( "The required element is "
+ XOR);
}
public static void main(String[] args)
{
int arr[] = { 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 };
int len = arr.length;
search(arr, len);
}
}
|
Python3
def search(arr, n) :
XOR = 0
for i in range (n) :
XOR = XOR ^ arr[i]
print ( "The required element is" , XOR)
arr = [ 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 ]
Len = len (arr)
search(arr, Len )
|
C#
using System;
class GFG{
static void search( int []arr, int n)
{
int XOR = 0;
for ( int i = 0; i < n; i++)
{
XOR = XOR ^ arr[i];
}
Console.Write( "The required element is " + XOR);
}
public static void Main(String[] args)
{
int []arr = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = arr.Length;
search(arr, len);
}
}
|
Javascript
<script>
function search(arr, n)
{
let XOR = 0;
for (let i = 0; i < n; i++) {
XOR = XOR ^ arr[i];
}
document.write( "The required element is " + XOR + "<br>" );
}
let arr = [ 1, 1, 2, 4, 4, 5, 5, 6, 6 ];
let len = arr.length;
search(arr, len);
</script>
|
OutputThe required element is 2
Time Complexity: O(n)
Auxiliary Space: O(1)
An Efficient Solution can find the required element in O(Log n) time. The idea is to use Binary Search. Below is an observation on the input array.
All elements before the required have the first occurrence at even index (0, 2, ..) and the next occurrence at odd index (1, 3, …). And all elements after the required elements have the first occurrence at an odd index and the next occurrence at an even index.
- Find the middle index, say ‘mid’.
- If ‘mid’ is even, then compare arr[mid] and arr[mid + 1]. If both are the same, then the required element after ‘mid’ and else before mid.
- If ‘mid’ is odd, then compare arr[mid] and arr[mid – 1]. If both are the same, then the required element after ‘mid’ and else before mid.
Below is the implementation based on the above idea:
C++
#include <iostream>
using namespace std;
void search( int arr[], int low, int high)
{
if (low > high)
return ;
if (low == high) {
cout << "The required element is " << arr[low];
return ;
}
int mid = (low + high) / 2;
if (mid % 2 == 0) {
if (arr[mid] == arr[mid + 1])
search(arr, mid + 2, high);
else
search(arr, low, mid);
}
else {
if (arr[mid] == arr[mid - 1])
search(arr, mid + 1, high);
else
search(arr, low, mid - 1);
}
}
int main()
{
int arr[] = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = sizeof (arr) / sizeof (arr[0]);
search(arr, 0, len - 1);
return 0;
}
|
C
#include <stdio.h>
void search( int * arr, int low, int high)
{
if (low > high)
return ;
if (low == high) {
printf ( "The required element is %d " , arr[low]);
return ;
}
int mid = (low + high) / 2;
if (mid % 2 == 0) {
if (arr[mid] == arr[mid + 1])
search(arr, mid + 2, high);
else
search(arr, low, mid);
}
else
{
if (arr[mid] == arr[mid - 1])
search(arr, mid + 1, high);
else
search(arr, low, mid - 1);
}
}
int main()
{
int arr[] = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = sizeof (arr) / sizeof (arr[0]);
search(arr, 0, len - 1);
return 0;
}
|
Java
public class Main {
public static void search( int [] arr, int low, int high)
{
if (low > high)
return ;
if (low == high) {
System.out.println( "The required element is "
+ arr[low]);
return ;
}
int mid = (low + high) / 2 ;
if (mid % 2 == 0 ) {
if (arr[mid] == arr[mid + 1 ])
search(arr, mid + 2 , high);
else
search(arr, low, mid);
}
else if (mid % 2 == 1 ) {
if (arr[mid] == arr[mid - 1 ])
search(arr, mid + 1 , high);
else
search(arr, low, mid - 1 );
}
}
public static void main(String[] args)
{
int [] arr = { 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 };
search(arr, 0 , arr.length - 1 );
}
}
|
Python
def search(arr, low, high):
if low > high:
return None
if low = = high:
return arr[low]
mid = low + (high - low) / 2
if mid % 2 = = 0 :
if arr[mid] = = arr[mid + 1 ]:
return search(arr, mid + 2 , high)
else :
return search(arr, low, mid)
else :
if arr[mid] = = arr[mid - 1 ]:
return search(arr, mid + 1 , high)
else :
return search(arr, low, mid - 1 )
arr = [ 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 ]
result = search(arr, 0 , len (arr) - 1 )
if result is not None :
print "The required element is %d" % result
else :
print "Invalid Array"
|
C#
using System;
class GFG {
public static void search( int [] arr, int low, int high)
{
if (low > high)
return ;
if (low == high) {
Console.WriteLine( "The required element is "
+ arr[low]);
return ;
}
int mid = (low + high) / 2;
if (mid % 2 == 0) {
if (arr[mid] == arr[mid + 1])
search(arr, mid + 2, high);
else
search(arr, low, mid);
}
else if (mid % 2 == 1) {
if (arr[mid] == arr[mid - 1])
search(arr, mid + 1, high);
else
search(arr, low, mid - 1);
}
}
public static void Main(String[] args)
{
int [] arr = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
search(arr, 0, arr.Length - 1);
}
}
|
Javascript
<script>
function search( arr, low, high)
{
if (low > high)
return ;
if (low == high) {
document.write( "The required element is " + arr[low]);
return ;
}
var mid = Math.floor((low + high) / 2);
if (mid % 2 == 0) {
if (arr[mid] == arr[mid + 1])
search(arr, mid + 2, high);
else
search(arr, low, mid);
}
else {
if (arr[mid] == arr[mid - 1])
search(arr, mid + 1, high);
else
search(arr, low, mid - 1);
}
}
var arr = [1, 1, 2, 4, 4, 5, 5, 6, 6];
var len = arr.length;
search(arr, 0, len - 1)
</script>
|
PHP
<?php
function search( $arr , $low , $high )
{
if ( $low > $high )
return ;
if ( $low == $high )
{
echo ( "The required element is " );
echo $arr [ $low ] ;
return ;
}
$mid = ( $low + $high ) / 2;
if ( $mid % 2 == 0)
{
if ( $arr [ $mid ] == $arr [ $mid + 1])
search( $arr , $mid + 2, $high );
else
search( $arr , $low , $mid );
}
else
{
if ( $arr [ $mid ] == $arr [ $mid - 1])
search( $arr , $mid + 1, $high );
else
search( $arr , $low , $mid - 1);
}
}
$arr = array (1, 1, 2, 4, 4, 5, 5, 6, 6);
$len = sizeof( $arr );
search( $arr , 0, $len - 1);
?>
|
OutputThe required element is 2
Time Complexity: O(Log n)
Auxiliary Space: O(1)
Note: Other Solutions to the question are slight variations of the approaches discussed in this post.
Another Approach: An Efficient Solution can find the required element in O(Log n) time. The idea is to use Binary Search without recursion. All elements before the required have the first occurrence at even index (0, 2, ..and so on) and the next occurrence at odd index (1, 3, ..and so on).
The approach will be as follows:
Find the middle index assuming mid using start pointer and end pointer. And check the mid element in the following cases
- Case 1) If mid element is not equal to mid+1 element and mid-1 element. This case returns the answer.
- Case 2) When mid element is even and equal to mid+1 element this means number is not present in the left side of the array. In this case start pointer will change to mid+1.
- Case 3) When mid element is odd and equal to mid-1 element this means number is not present in the left side of the array. In this case start pointer will change to mid+1.
- Case 4) When mid element is odd and equal to mid+1 element this means number is not present in the right side of the array. In this case end pointer will change to mid-1.
- Case 5) When mid element is even and equal to mid-1 element this means number is not present in the right side of the array. In this case end pointer will change to mid-1.
Check for all case for possible values of mid till start<=end..
If all checks fail there is no such element.
This solution requires extra checks for edge cases.
- Edge Case 1) If only one element is present in the array. Therefore return the only element of the array.
- Edge Case 2) If last element of the array is the required element. Therefore return the last element of the array.
- Edge Case 3) If first element of the array is the required element. Therefore return the first element of the array.
Below is the implementation based on the above idea:
C++
#include <iostream>
using namespace std;
int search( int nums[], int n)
{
int start = 0, end = n - 1, mid;
if (n == 1)
return nums[0];
if (nums[start]
!= nums[start + 1])
return nums[start];
if (nums[end]
!= nums[end - 1])
return nums[end];
while (start <= end)
{
mid = start + (end - start) / 2;
if (nums[mid] != nums[mid - 1]
&& nums[mid] != nums[mid + 1])
return nums[mid];
else if ((nums[mid] == nums[mid + 1]
&& mid % 2 == 0)
|| (nums[mid] == nums[mid - 1]
&& mid % 2 != 0))
start = mid + 1;
else
end = mid - 1;
}
return -1;
}
int main()
{
int arr[] = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int n = sizeof (arr) / sizeof (arr[0]);
int element = search(arr, n);
if (element != -1)
cout << "The required element is " << element;
else
cout << "There is no such element" ;
}
|
Java
class GFG {
public static int search( int [] nums)
{
int start = 0 , end = nums.length - 1 , mid;
if (nums.length
== 1 )
return nums[ 0 ];
if (nums[start]
!= nums[start + 1 ])
return nums[start];
if (nums[end]
!= nums[end
- 1 ])
return nums[end];
while (start <= end) {
mid = start + (end - start) / 2 ;
if (nums[mid] != nums[mid - 1 ]
&& nums[mid] != nums[mid + 1 ])
return nums[mid];
else if ((nums[mid] == nums[mid + 1 ]
&& mid % 2 == 0 )
|| (nums[mid] == nums[mid - 1 ]
&& mid % 2 != 0 ))
start = mid + 1 ;
else
end = mid - 1 ;
}
return - 1 ;
}
public static void main(String[] args)
{
int [] arr = { 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 };
int element = search(arr);
if (element != - 1 )
System.out.println( "The required element is "
+ element);
else
System.out.println( "There is no such element" );
}
}
|
Python3
def search(nums):
start = 0 ;
end = len (nums) - 1 ;
mid = 0 ;
if ( len (nums) = = 1 ):
return nums[ 0 ];
if (nums[start] ! = nums[start + 1 ]):
return nums[start];
if (nums[end] ! = nums[end - 1 ]):
return nums[end];
while (start < = end):
mid = start + (end - start) / / 2 ;
if (nums[mid] ! = nums[mid - 1 ] and nums[mid] ! = nums[mid + 1 ]):
return nums[mid];
elif ((nums[mid] = = nums[mid + 1 ] and mid % 2 = = 0 ) or (nums[mid] = = nums[mid - 1 ] and mid % 2 ! = 0 )):
start = mid + 1 ;
else :
end = mid - 1 ;
return - 1 ;
if __name__ = = '__main__' :
arr = [ 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 ];
element = search(arr);
if (element ! = - 1 ):
print ( "The required element is " , element);
else :
print ( "There is no such element" );
|
C#
using System;
public class GFG {
public static int search( int [] nums)
{
int start = 0, end = nums.Length - 1, mid;
if (nums.Length
== 1)
return nums[0];
if (nums[start]
!= nums[start + 1])
return nums[start];
if (nums[end]
!= nums[end
- 1])
return nums[end];
while (start <= end)
{
mid = start + (end - start) / 2;
if (nums[mid] != nums[mid - 1]
&& nums[mid] != nums[mid + 1])
return nums[mid];
else if ((nums[mid] == nums[mid + 1]
&& mid % 2 == 0)
|| (nums[mid] == nums[mid - 1]
&& mid % 2 != 0))
start = mid + 1;
else
end = mid - 1;
}
return -1;
}
public static void Main(String[] args)
{
int [] arr = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int element = search(arr);
if (element != -1)
Console.WriteLine( "The required element is "
+ element);
else
Console.WriteLine( "There is no such element" );
}
}
|
Javascript
<script>
function search(nums)
{
var start = 0, end = nums.length - 1, mid;
if (nums.length
== 1)
return nums[0];
if (nums[start]
!= nums[start + 1])
return nums[start];
if (nums[end]
!= nums[end
- 1])
return nums[end];
while (start <= end)
{
mid = start + (end - start) / 2;
if (nums[mid] != nums[mid - 1]
&& nums[mid] != nums[mid + 1])
return nums[mid];
else if ((nums[mid] == nums[mid + 1]
&& mid % 2 == 0)
|| (nums[mid] == nums[mid - 1]
&& mid % 2 != 0))
start = mid + 1;
else
end = mid - 1;
}
return -1;
}
var arr = [ 1, 1, 2, 4, 4, 5, 5, 6, 6 ];
var element = search(arr);
if (element = 2)
document.write( "The required element is "
+ element);
else
document.write( "There is no such element" );
</script>
|
OutputThe required element is 2
This solution is contributed by Arnav Sharma.
Time Complexity: O(logn)
Auxiliary Space: O(1)
This article is contributed by Mehboob Elahi. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Another Approach:-
We can simply use hashmap to store the frequency of the elements and after that we can just traverse the hashmap to find the element with frequency 1.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
void search( int arr[], int n)
{
unordered_map< int , int > mm;
for ( int i = 0; i < n; i++) {
mm[arr[i]]++;
}
for ( auto x : mm) {
if (x.second == 1) {
cout << x.first << endl;
break ;
}
}
}
int main()
{
int arr[] = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = sizeof (arr) / sizeof (arr[0]);
search(arr, len);
return 0;
}
|
Java
import java.util.*;
class GFG {
static void search( int arr[], int n)
{
HashMap<Integer,Integer> mm= new HashMap<Integer,Integer>();
for ( int i = 0 ; i < arr.length; i++) {
if (mm.containsKey(arr[i])) {
int count = mm.get(arr[i]) + 1 ;
mm.put(arr[i], count);
} else {
mm.put(arr[i], 1 );
}
}
for (Map.Entry<Integer,Integer> x : mm.entrySet()){
int c= x.getValue();
if (c == 1 ){
System.out.println(x.getKey());
break ;
}
}
}
public static void main(String[] args) {
int arr[] = { 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 };
int len = arr.length;
search(arr, len);
return ;
}
}
|
Python3
def search(arr):
freq = {}
for i in arr:
if i in freq:
freq[i] + = 1
else :
freq[i] = 1
for key, value in freq.items():
if value = = 1 :
print (key)
break
if __name__ = = '__main__' :
arr = [ 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 ]
search(arr)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static void Search( int [] arr, int n) {
Dictionary< int , int > mm = new Dictionary< int , int >();
for ( int i = 0; i < arr.Length; i++) {
if (mm.ContainsKey(arr[i])) {
int count = mm[arr[i]] + 1;
mm[arr[i]] = count;
} else {
mm.Add(arr[i], 1);
}
}
foreach (KeyValuePair< int , int > x in mm) {
int c = x.Value;
if (c == 1){
Console.WriteLine(x.Key);
break ;
}
}
}
public static void Main( string [] args) {
int [] arr = { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
int len = arr.Length;
Search(arr, len);
return ;
}
}
|
Javascript
function search(arr){
let freq = {};
for (let i of arr){
if (i in freq){
freq[i] += 1;
}
else {
freq[i] = 1;
}
}
for (let [key, value] of Object.entries(freq)){
if (value == 1){
console.log(key);
break ;
}
}
}
arr = [1, 1, 2, 4, 4, 5, 5, 6, 6];
search(arr);
|
Time Complexity:- O(N)
Auxiliary Space:- O(N)
Another Approach Using Stacks:
We know that the given array is sorted in non-decreasing (ascending) order, and that every element occurs twice except for 1 element. The approach involves using a stack while iterating through the entire array. While pushing in elements, we may push this singular element on to the stack. By the end of the iteration we will have that singular element on the top of the stack which is returned.
While iterating through the array, if we have no element in the stack, or the consective element is not equal to the top most element in the stack, we can push that element to the stack. Else we can pop the top element from the stack. Finally, we can return the top most element, which is the singular element in the array.
C++
#include <bits/stdc++.h>
using namespace std;
int singleNonDuplicate(vector< int >& nums) {
stack< int > stk;
for ( int i = 0; i < nums.size(); i++) {
if (stk.empty() or nums[i] != stk.top()) {
stk.push(nums[i]);
} else {
stk.pop();
}
}
return stk.top();
}
int main()
{
vector< int > arr{ 1, 1, 2, 4, 4, 5, 5, 6, 6 };
cout<<singleNonDuplicate(arr)<<endl;
return 0;
}
|
Java
import java.util.Stack;
public class GFG {
public static int singleNonDuplicate( int [] nums) {
Stack<Integer> stk = new Stack<>();
for ( int i = 0 ; i < nums.length; i++) {
if (stk.isEmpty() || nums[i] != stk.peek()) {
stk.push(nums[i]);
} else {
stk.pop();
}
}
return stk.peek();
}
public static void main(String[] args) {
int [] arr = { 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 };
System.out.println(singleNonDuplicate(arr));
}
}
|
Python3
def singleNonDuplicate(nums):
stack = []
for num in nums:
if not stack or num ! = stack[ - 1 ]:
stack.append(num)
else :
stack.pop()
return stack[ - 1 ]
if __name__ = = "__main__" :
arr = [ 1 , 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 ]
print (singleNonDuplicate(arr))
|
C#
using System;
using System.Collections.Generic;
namespace SingleNonDuplicate
{
class Program
{
static int SingleNonDuplicate(List< int > nums)
{
Stack< int > stk = new Stack< int >();
foreach ( int num in nums)
{
if (stk.Count == 0 || num != stk.Peek())
{
stk.Push(num);
}
else
{
stk.Pop();
}
}
return stk.Peek();
}
static void Main( string [] args)
{
List< int > arr = new List< int > { 1, 1, 2, 4, 4, 5, 5, 6, 6 };
Console.WriteLine(SingleNonDuplicate(arr));
}
}
}
|
Javascript
function singleNonDuplicate(nums) {
const stack = [];
for (let i = 0; i < nums.length; i++) {
if (stack.length === 0 || nums[i] !== stack[stack.length - 1]) {
stack.push(nums[i]);
} else {
stack.pop();
}
}
return stack[0];
}
const arr = [1, 1, 2, 4, 4, 5, 5, 6, 6];
console.log(singleNonDuplicate(arr));
|
Output:
2
Time Complexity:- O(N) for traversing through entire array linearly.
Auxiliary Space:- O(N) for stroing the elements in stack.