zoukankan      html  css  js  c++  java
  • 笔试算法总结一:位操作

    1、数组A[n],除数字X之外,其他的数字都出现了三次。X只出现了一次。什么方法可以很快的求出X。

      思路:假设数组为A[6] = {1,5,5,1,1,5}; 此时数组中所有的数字都出现了三次。我们考察一下这些数字的二进制存储形式。

      A[0] = 1 : 0 0 1

      A[1] = 5 : 1 0 1

      A[2] = 5 : 1 0 1

          A[3] = 1 : 0 0 1

          A[4] = 1 : 0 0 1

          A[5] = 5 : 1 0

      可以发现将所有数字的某一个bit位对应的 1 的个数正好可以整除3.最低位1的个数为6,最高位1的个数为3,中间1的个数为0. 6、3、0除以3都可以整除。

    此时,若数组中添加任意另外一个不同的数Y,Y的二进制形式必然与当前数字的二进制形式不同,会导致某些位置的 1 的个数不能再整除 3,因此我们就可以

    知道Y在哪些位置出现了1.由此可以反推Y的值。

    解法分为三个部分:(1) 计算当前所有数组元素二进制位置 i[1,32]上1的个数。(2)若i位置1的个数不能整除3,则X的二进制对应的此位置应当为1.

               (3)计算X。

    代码:

    #include<stdio.h>
    #include<stdlib.h>
    int main(char *argv[], int argc)
    {
        int i = 0;
        int j = 0;
        int k = 0;
        int A[7] = {12,12,12,13,13,13,17};
        int Ones[32] = {0};
    
        int ResultX = 0;
    
        for(i=0; i<7; i++)
            for(j=0; j<32; j++)
        {
            k = (A[i]>>j) & 1;
            Ones[j] += k;
        }
        
        for (i=0; i<32 ;i++ )
        {
            printf("%3d",Ones[i]%3);
            if(Ones[i]%3 != 0)
                ResultX += (1<<i);
        }
    
        printf("X Is :%d
    ",ResultX);
        system("PAUSE");    
        return 0;
    }
    View Code

    2、 倘若此时把题意换一下:数组A[n],除X外其他的数都出现两次,X出现一次。求X。怎么做呢?

      其实此时的题目变得更加简单了。看一个操作:异或。

      7 : 1 1 1

    异或

          7 : 1 1 1

    异或

      5:  1 0 1

      最终的结果是5: 101。所以出现两次的数都被自身的异或抵消没了,剩下的都是指出现一次或者奇数次的数。受此启发,我们不难写出这样的代码来计算

    一个数组中只出现了一次的X:

    int X = 0for (int i=0; i<n ; i++ ){
        X = X ^ A[i];
    }
    
    printf("Unique Number X  is : %d", X);

    3、再考虑一个问题:若果数组A[n]中有两个不同的数X,Y。除X,Y之外,其他的数字都出现了两次,求X和Y。

      参考(2)中的讨论,倘若我们可以把X和Y分到两个子数组中,而且两个子数组都满足:除X外其他的数都出现两次,X出现一次。那么我们使用(2)中的方法

    就可以把X和Y求出来的。

    代码如下:

    int firstOnePos(int data)
    {
        int k = 0;
        int i = 0;
        
        for (i=0; i<32; i++)
        {
            k = (data >> i) & 1;
            if (k == 1)
                return i;
        }
        return -1;
    }
    int testBit(int data,int pos)
    {
        return (data>>pos) & 1;
    }
    int main(char *argv[], int argc)
    {
        int i = 0;
        int j = 0;     int pos = 0;
        int A[6] = {12,12,15,13,13,17};
        int Ones[32] = {0};
    
        int Z = 0;
        int X = 0;
        int Y = 0;
        
        for (i=0; i<6 ;i++ )
        {
            Z = Z ^ A[i];
        }
        pos = firstOnePos(Z);
        if(pos == -1)
           return 0;
           
        for(i=0; i<6; i++)
        {
             if(testBit(A[i],pos))
                X = X ^ A[i];
             else
                Y = Y ^ A[i];
        }
        
        printf("X Is :%d
    ",X);
        printf("Y Is :%d
    ",Y);
        system("PAUSE");    
        return 0;
    }
    View Code
  • 相关阅读:
    3288 积木大赛
    3284 疯狂的黄大神
    1531 山峰
    1018 单词接龙
    1432 总数统计
    1507 酒厂选址
    1063 合并果子
    几个sort不能过的题目
    poj 2245 Lotto
    求两圆相交面积模板
  • 原文地址:https://www.cnblogs.com/tju-gsp/p/3660110.html
Copyright © 2011-2022 走看看