Find the element that appears once

来源:互联网 发布:家装平面模板软件 编辑:程序博客网 时间:2024/05/21 19:26

来源:http://www.geeksforgeeks.org/find-the-element-that-appears-once/


问题:在一个数组中,其中有一个元素只出现一次,其余元素都出现三次,如何在O(n)的时间复杂度和O(1)的复杂度内找到那个元素。


首先我的想法是,一个数如果出现了三次,则这个数的二进制对应的位上1的个数肯定为3.这样我们可以枚举每一位,计算所有数在该位上1的和,如果这个和不是3的倍数,则多出的那个1肯定是由只出现过一次的那个值提供的,这样我们可以实现复杂度为O(30*n)和O(1)的空间复杂度解决该问题,这也是这篇文章中所说的第二种方法。相传这是谷歌的面试题,我给第一种做法的作者跪了,我还是没看懂。位运算真是太神奇了,许多东西需要慢慢去体会。


第一种思路的代码:

#include <stdio.h> int getSingle(int arr[], int n){    int ones = 0, twos = 0 ;     int common_bit_mask;     // Let us take the example of {3, 3, 2, 3} to understand this    for( int i=0; i< n; i++ )    {        /* The expression "one & arr[i]" gives the bits that are           there in both 'ones' and new element from arr[].  We           add these bits to 'twos' using bitwise OR            Value of 'twos' will be set as 0, 3, 3 and 1 after 1st,           2nd, 3rd and 4th iterations respectively */        twos  = twos | (ones & arr[i]);          /* XOR the new bits with previous 'ones' to get all bits           appearing odd number of times            Value of 'ones' will be set as 3, 0, 2 and 3 after 1st,           2nd, 3rd and 4th iterations respectively */        ones  = ones ^ arr[i];          /* The common bits are those bits which appear third time           So these bits should not be there in both 'ones' and 'twos'.           common_bit_mask contains all these bits as 0, so that the bits can            be removed from 'ones' and 'twos'               Value of 'common_bit_mask' will be set as 00, 00, 01 and 10           after 1st, 2nd, 3rd and 4th iterations respectively */        common_bit_mask = ~(ones & twos);          /* Remove common bits (the bits that appear third time) from 'ones'                        Value of 'ones' will be set as 3, 0, 0 and 2 after 1st,           2nd, 3rd and 4th iterations respectively */        ones &= common_bit_mask;          /* Remove common bits (the bits that appear third time) from 'twos'            Value of 'twos' will be set as 0, 3, 1 and 0 after 1st,           2nd, 3rd and 4th itearations respectively */        twos &= common_bit_mask;         // uncomment this code to see intermediate values        //printf (" %d %d \n", ones, twos);    }     return ones;} int main(){    int arr[] = {3, 3, 2, 3};    int n = sizeof(arr) / sizeof(arr[0]);    printf("The element with single occurrence is %d ",            getSingle(arr, n));    return 0;}

Output:

2

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


第二种方法是我们容易想到的,程序代码如下:

#include <stdio.h>#define INT_SIZE 32 int getSingle(int arr[], int n){    // Initialize result    int result = 0;     int x, sum;     // Iterate through every bit    for (int i = 0; i < INT_SIZE; i++)    {      // Find sum of set bits at ith position in all      // array elements      sum = 0;      x = (1 << i);      for (int j=0; j< n; j++ )      {          if (arr[j] & x)            sum++;      }       // The bits with sum not multiple of 3, are the      // bits of element with single occurrence.      if (sum % 3)        result |= x;    }     return result;} // Driver program to test above functionint main(){    int arr[] = {12, 1, 12, 3, 12, 1, 1, 2, 3, 2, 2, 3, 7};    int n = sizeof(arr) / sizeof(arr[0]);    printf("The element with single occurrence is %d ",            getSingle(arr, n));    return 0;}


0 0