📜  在重复元素/唯一数字2的数组中找到两个不重复的元素

📅  最后修改于: 2021-04-27 21:55:58             🧑  作者: Mango

SG问
给定一个数组,其中除两个以外的所有数字都重复一次。 (即,我们有2n + 2个数字,n个数字出现了两次,其余两个数字出现了一次)。以最有效的方式找到这两个数字。

方法1(使用排序)
首先,对所有元素进行排序。在排序数组中,通过比较相邻元素,我们可以轻松获得非重复元素。该方法的时间复杂度为O(nLogn)

方法2(使用XOR)
令x和y为我们正在寻找的非重复元素,而arr []为输入数组。首先,计算所有数组元素的XOR。

xor = arr[0]^arr[1]^arr[2].....arr[n-1]

在xor中设置的所有位将在一个非重复元素(x或y)中设置,而在其他元素中则不设置。因此,如果我们将xor的任何设置位取整,然后将数组的元素分为两组-一组具有相同位设置的元素,而另一组没有设置相同位的元素。这样,我们将在一组中获得x,在另一组中获得y。现在,如果我们对第一个集合中的所有元素进行XOR,我们将获得第一个非重复元素,而在其他集合中进行同样的操作,我们将获得第二个非重复元素。

Let us see an example.
   arr[] = {2, 4, 7, 9, 2, 4}
1) Get the XOR of all the elements.
     xor = 2^4^7^9^2^4 = 14 (1110)
2) Get a number which has only one set bit of the xor.   
   Since we can easily get the rightmost set bit, let us use it.
     set_bit_no = xor & ~(xor-1) = (1110) & ~(1101) = 0010
   Now set_bit_no will have only set as rightmost set bit of xor.
3) Now divide the elements in two sets and do xor of         
   elements in each set and we get the non-repeating 
   elements 7 and 9. Please see the implementation for this step.

方法 :
步骤1:将数组中的所有元素异或为变量总和,因此数组中两次出现的所有元素都将被删除,例如4 =“ 100”,如果4 xor 4 =>“ 100” xor“ 100”答案将是“ 000”。
步骤2:因此,总和的最终答案将是3 xor 5,因为2和4都是xor且自身给出0,因此sum =“ 011” xor“ 101”,即sum =“ 110” = 6。
步骤3:现在我们将取2的总和,即(-sum)=“ 010”。
步骤4:现在按位求和与和的2的总和,即“ 110”和“ 010”给出答案“ 010”(按位&的目的是要得到一个仅包含和的最右边设置位的数字)。
步骤5:按位求和该数组所有元素的总和,即2 =“ 010”和“ 010” = 2、3 =“ 011”和“ 010” =“ 010”,4 =“ 100”和“ 010” ” =“ 000”,5 =“ 101”和“ 010” =“ 000”。
步骤6:正如我们看到的,2,3> 0的按位&导致它们与sum1异或,而4,5的按位&导致结果为0因此它们将与sum2异或。
步骤7:由于2出现了两次,所以与sum1进行两次xor运算仅将结果3存储在其中;由于4也出现了两次,因此与sum2进行xor运算将取消它的值,因此仅保留5。

执行:

C++
// C++ proogram for above approach
#include 
using namespace std;
 
/* This function sets the values of
*x and *y to non-repeating elements
in an array arr[] of size n*/
void get2NonRepeatingNos(int arr[], int n,
                                int *x, int *y)
{
    /* Will hold Xor of all elements */
    int Xor = arr[0];
   
    /* Will have only single set bit of Xor */
    int set_bit_no;
    int i;
    *x = 0;
    *y = 0;
     
    /* Get the Xor of all elements */
    for(i = 1; i < n; i++)
    Xor ^= arr[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 < n; i++)
    { 
         
      /*Xor of first set */
      if(arr[i] & set_bit_no)
        *x = *x ^ arr[i];
      /*Xor of second set*/
      else
      {
        *y = *y ^ arr[i];
      }
    }
}
 
/* Driver code */
int main()
{
    int arr[] = {2, 3, 7, 9, 11, 2, 3, 11};
    int n = sizeof(arr)/sizeof(*arr);
    int *x = new int[(sizeof(int))];
    int *y = new int[(sizeof(int))];
    get2NonRepeatingNos(arr, n, x, y);
    cout<<"The non-repeating elements are "<<*x<<" and "<<*y;
}
 
// This code is contributed by rathbhupendra


C
// C program for above approach
#include 
#include 
 
/* This function sets the values of
*x and *y to non-repeating elements
in an array arr[] of size n*/
void get2NonRepeatingNos(int arr[], int n,
                                int *x, int *y)
{
    /* Will hold Xor of all elements */
    int Xor = arr[0];
   
    /* Will have only single set bit of Xor */
    int set_bit_no;
    int i;
    *x = 0;
    *y = 0;
     
    /* Get the Xor of all elements */
    for(i = 1; i < n; i++)
    Xor ^= arr[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 < n; i++)
    { 
         
      /*Xor of first set */
      if(arr[i] & set_bit_no)
        *x = *x ^ arr[i];
      /*Xor of second set*/
      else
      {
        *y = *y ^ arr[i];
      }
    }
}
 
 
/* Driver program to test above function */
int main()
{
  int arr[] = {2, 3, 7, 9, 11, 2, 3, 11};
  int *x = (int *)malloc(sizeof(int));
  int *y = (int *)malloc(sizeof(int));
  get2NonRepeatingNos(arr, 8, x, y);
  printf("The non-repeating elements are %d and %d", *x, *y);
  getchar();
}


Java
//Java Program for above approach
 
public class UniqueNumbers {
   
    // This function sets the values of
    // *x and *y to non-repeating elements
    // in an array arr[] of size n
    public static void UniqueNumbers2(int[] arr,int n)
    {
        int sum =0;
        for(int i = 0;i 0
            if((arr[i]&sum) > 0)
            {
 
                // if result > 0 then arr[i] xored
                // with the sum1
                sum1 = (sum1^arr[i]);
            }
            else
            {
                // if result == 0 then arr[i]
                // xored with sum2
                sum2 = (sum2^arr[i]);
            }
        }
 
        // print the the two unique numbers
        System.out.println("The non-repeating elements are "+
                                          sum1+" and "+sum2);
    }
 
    public static void main(String[] args)
    {
        int[] arr = new int[]{2, 3, 7, 9, 11, 2, 3, 11};
        int n = arr.length;
        UniqueNumbers2(arr,n);
    }
}
// This code is contributed by Parshav Nahta


Python3
# Python3 program for above approach
 
# This function sets the values of
# *x and *y to non-repeating elements
# in an array arr[] of size n
def UniqueNumbers2(arr, n):
   
  sums = 0
   
  for i in range(0, n):
     
    # Xor  all the elements of the array
    # all the elements occuring twice will
    # cancel out each other remaining
    # two unnique numbers will be xored
    sums = (sums ^ arr[i])
     
  # Bitwise & the sum with it's 2's Complement
  # Bitwise & will give us the sum containing
  # only the rightmost set bit
  sums = (sums & -sums)
 
  # sum1 and sum2 will contains 2 unique
  # elements elements initialized with 0 box
  # number xored with 0 is number itself
  sum1 = 0
  sum2 = 0
 
  # Traversing the array again
  for i in range(0, len(arr)):
     
    # Bitwise & the arr[i] with the sum
    # Two possibilities either result == 0
    # or result > 0
    if (arr[i] & sums) > 0:
       
      # If result > 0 then arr[i] xored
      # with the sum1
      sum1 = (sum1 ^ arr[i])
       
    else:
       
      # If result == 0 then arr[i]
      # xored with sum2
      sum2 = (sum2 ^ arr[i])
 
  # Print the the two unique numbers
  print("The non-repeating elements are ",
         sum1 ," and ", sum2)
 
# Driver Code
if __name__ == "__main__":
   
    arr = [ 2, 3, 7, 9, 11, 2, 3, 11 ]
    n = len(arr)
     
    UniqueNumbers2(arr, n)
 
# This code is contributed by akhilsaini


C#
// C# program for above approach
using System;
 
class GFG{
 
// This function sets the values of
// *x and *y to non-repeating elements
// in an array arr[] of size n
static void UniqueNumbers2(int[] arr, int n)
{
    int sum = 0;
    for(int i = 0; i < n; i++)
    {
         
        // Xor  all the elements of the array
        // all the elements occuring twice will
        // cancel out each other remaining
        // two unnique numbers will be xored
        sum = (sum ^ arr[i]);
    }
 
    // Bitwise & the sum with it's 2's Complement
    // Bitwise & will give us the sum containing
    // only the rightmost set bit
    sum = (sum & -sum);
 
    // sum1 and sum2 will contains 2 unique
    // elements elements initialized with 0 box
    // number xored with 0 is number itself
    int sum1 = 0;
    int sum2 = 0;
 
    // Traversing the array again
    for(int i = 0; i < arr.Length; i++)
    {
         
        // Bitwise & the arr[i] with the sum
        // Two possibilities either result == 0
        // or result > 0
        if ((arr[i] & sum) > 0)
        {
             
            // If result > 0 then arr[i] xored
            // with the sum1
            sum1 = (sum1 ^ arr[i]);
        }
        else
        {
             
            // If result == 0 then arr[i]
            // xored with sum2
            sum2 = (sum2 ^ arr[i]);
        }
    }
 
    // Print the the two unique numbers
    Console.WriteLine("The non-repeating " +
                      "elements are " + sum1 +
                      " and " + sum2);
}
 
// Driver Code
static public void Main()
{
    int[] arr = { 2, 3, 7, 9, 11, 2, 3, 11 };
    int n = arr.Length;
     
    UniqueNumbers2(arr, n);
}
}
 
// This code is contributed by akhilsaini


输出:

The non-repeating elements are 7 and 9

时间复杂度: O(n)
辅助空间: O(1)

请参考以下帖子以获取详细说明:
在未排序的数组中找到出现奇数的两个数字