笔试算法总结一:位操作

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\n",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\n",X);
    printf("Y Is :%d\n",Y);
    system("PAUSE");    
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/tju-gsp/p/3660110.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值