`

Find the two repeating elements in a given array

 
阅读更多

You are given an array of n+2 elements. All elements of the array are in range 1 to n. And all elements occur once except two numbers which occur twice. Find the two repeating numbers.

For example, array = {4, 2, 4, 5, 2, 3, 1} and n = 5

The above array has n + 2 = 7 elements with all elements occurring once except 2 and 4 which occur twice. So the output should be 4 2.

 

Method 1 (Use Count array)
Traverse the array once. While traversing, keep track of count of all elements in the array using a temp array count[] of size n, when you see an element whose count is already set, print it as duplicate.

This method uses the range given in the question to restrict the size of count[], but doesn’t use the data that there are only two repeating elements.

void findRepeating(int arr[], int size) {
  int *count = (int *)calloc(sizeof(int), (size - 2));
  int i;
   
  printf(" Repeating elements are ");
  for(i = 0; i < size; i++) {  
    if(count[arr[i]] == 1)
      printf(" %d ", arr[i]);
    else
     count[arr[i]]++;
  }    
}    

Time Complexity: O(n)
Auxiliary Space: O(n)

 

Method 2 (Use XOR)
Let the repeating numbers be X and Y, if we xor all the elements in the array and all integers from 1 to n, then the result is X xor Y.
The 1’s in binary representation of X xor Y is corresponding to the different bits between X and Y. Suppose that the kth bit of X xor Y is 1, we can xor all the elements in the array and all integers from 1 to n, whose kth bits are 1. The result will be one of X and Y.

void findRepeating(int arr[], int size) {
  int xor = arr[0]; /* Will hold xor of all elements */
  int set_bit_no;  /* Will have only single set bit of xor */
  int i;
  int n = size - 2;
  int x = 0, y = 0;
   
  /* Get the xor of all elements in arr[] and {1, 2 .. n} */
  for(i = 1; i < size; i++)
    xor ^= arr[i];  
  for(i = 1; i <= n; i++)
    xor ^= i;   
 
  /* Get the rightmost set bit in set_bit_no */
  set_bit_no = xor & ~(xor-1);
 
  /* Now divide elements in two sets by comparing rightmost set
   bit of xor with bit at same position in each element. */
  for(i = 0; i < size; i++) {
    if(arr[i] & set_bit_no)
      x = x ^ arr[i]; /*XOR of first set in arr[] */
    else
      y = y ^ arr[i]; /*XOR of second set in arr[] */
  }
  for(i = 1; i <= n; i++) {
    if(i & set_bit_no)
      x = x ^ i; /*XOR of first set in arr[] and {1, 2, ...n }*/
    else
      y = y ^ i; /*XOR of second set in arr[] and {1, 2, ...n } */
  }
   
  printf("\n The two repeating elements are %d & %d ", x, y);
}   

Time Complexity: O(n)
Auxiliary Space: O(1)

更好理解的java版本:

A[i]: 3,2,2,3,4,1

    i: 0,1,2,3,4,5

    j: 0,1,2,3,4,0

X = X ^ A[i] ^ j, 循环之后的X的结果就是重复的两个数2,3的异或。

public void findTwoRepeatingNumbers(int[] A) {
	int x = 0;
	for(int i=0; i<A.length; i++) {
		int j = (i!=A.length-1) ? i : 0;
		x ^= A[i] ^ j;
	}
	int lsb = x & -x;
	int a = 0, b = 0;
	for(int i=0; i<A.length; i++) {
		if((A[i]&lsb) == lsb) {
			a ^= A[i];
		} else {
			b ^= A[i];
		}
		
		int j = (i!=A.length-1) ? i : 0;
		if((j&lsb) == lsb) {
			a ^= j;
		} else {
			b ^= j;
		}
	}
	System.out.println("a="+a + ", b="+b);
}

 

 

Method 3 (Use array elements as index)

Traverse the array. Do following for every index i of A[].
{
check for sign of A[abs(A[i])] ;
if positive then
   make it negative by   A[abs(A[i])]=-A[abs(A[i])];
else  // i.e., A[abs(A[i])] is negative
   this   element (ith element of list) is a repetition
}
Example: A[] =  {1, 1, 2, 3, 2}
i=0; 
Check sign of A[abs(A[0])] which is A[1].  A[1] is positive, so make it negative. 
Array now becomes {1, -1, 2, 3, 2}

i=1; 
Check sign of A[abs(A[1])] which is A[1].  A[1] is negative, so A[1] is a repetition.

i=2; 
Check sign of A[abs(A[2])] which is A[2].  A[2] is  positive, so make it negative. '
Array now becomes {1, -1, -2, 3, 2}

i=3; 
Check sign of A[abs(A[3])] which is A[3].  A[3] is  positive, so make it negative. 
Array now becomes {1, -1, -2, -3, 2}

i=4; 
Check sign of A[abs(A[4])] which is A[2].  A[2] is negative, so A[4] is a repetition. 

Note that this method modifies the original array and may not be a recommended method if we are not allowed to modify the array. 

void findRepeating(int arr[], int size) {
  int i;  
  
  printf("\n The repeating elements are");
   
  for(i = 0; i < size; i++) {
    if(arr[abs(arr[i])] > 0)
      arr[abs(arr[i])] = -arr[abs(arr[i])];
    else
      printf(" %d ", abs(arr[i]));
  }         
}   

Reference:

http://www.geeksforgeeks.org/find-the-two-repeating-elements-in-a-given-array/

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics