zoukankan      html  css  js  c++  java
  • 笔试算法题(34):从数字序列中寻找仅出现一次的数字 & 最大公约数(GCD)问题

    出题:给定一个数字序列,其中每个数字最多出现两次,只有一个数字仅出现了一次,如何快速找出其中仅出现了一次的数字;

    分析:

    • 由于知道一个数字异或操作它本身(X^X=0)都为0,而任何数字异或操作0都为它本身,所以当所有的数字序列都异或操作之后,所有出现两次的数字异或操作之后的结果都为0,则最后剩下的结果就是那个仅出现了一次的数字;
    • 如果有多个数字都仅仅出现了一次,则上述的异或操作方法不再适用;如果确定只有两个数字只出现了一次,则可以利用X+Y=a和XY=b求解;

    解题:

     1 int findSingleInt(int *array, int length) {
     2         int result=0;
     3         for(int i=0;i<length;i++)
     4                 result^=array[i];
     5         return result;
     6 }
     7 
     8 int main() {
     9         int array[]={1,2,3,4,5,1,2,3,4,5,6};
    10         printf("%d
    ",findSingleInt(array,11));
    11         return 0;
    12 }

    出题:求两个正整数的最大公约数,如果正整数较大,该如何处理;

    分析:

    • 辗转相除法:gcd(x,y)=gcd(y,x%y),直到较小一个数(y%x)为0,此时的y就为最大公约数。对于大整数而言,取模运算(%)开销较大 (用到除法),所以不适合计算较大整数间的GCD,注意到既然y与x%y的gcd等于x和y的gcd,那么x-y与y的gcd同样等于x和y的 gcd,gcd(x,y)=gcd(x,x-y)这样就可以避免除法操作,但经历更多的循环,同样需要保证x>y;
    • 另外还有一个终极解法:使用移位操作和减法操作替代除法。
      首先,如果y=k*y1, x=k*x1,则有gcd(y, x)=k*gcd(y1, x1)
      然后,如果x=p*x1, y%p!=0,p是素数,则有gcd(x, y)=gcd(x1, y)
      所以当p=2的时候
      如果x和y都是偶数,gcd(x, y)=2*gcd(x>>1, y>>1)
      如果x为偶数,y为奇数,gcd(x,y)=gcd(x>>1, y)
      如果x为奇数,y为偶数,gcd(x, y)=gcd(x, y>>1)
      如果x和y都是奇数,gcd(x, y)=gcd(x, x-y),x-y必然会是偶数

    解题:

     1 int gcd1(int x, int y) {
     2         return (y==0) ? x:gcd1(y,x%y);
     3 }
     4 
     5 int gcd2(int x, int y) {
     6         if(x<y)
     7                 return gcd2(y,x);
     8         if(y==0)
     9                 return x;
    10         else
    11                 return gcd2(x-y,y);
    12 }
    13 
    14 int gcd3(int x, int y) {
    15         if(x<y)
    16                 return gcd3(y,x);
    17         if(y==0)
    18                 return x;
    19         else {
    20                 if(x%2==0) {
    21                         if(y%2==0)
    22                                 return (gcd3(x >> 1, y >> 1) << 1);
    23                         else
    24                                 return gcd3(x >> 1,y);
    25                 } else {
    26                         if(y%2==0)
    27                                 return gcd3(x,y >> 1);
    28                         else
    29                                 return gcd3(y,x-y);
    30                 }
    31         }
    32 }
  • 相关阅读:
    C++ Sqlite3的基本使用
    DirectX11 初探XMVECOTR&XMMATRIX
    lib和dll文件的初了解
    游戏设计模式——C++单例类
    C++11智能指针的深度理解
    你的文章里为什么不放源码Github链接了
    堡垒机的核心武器:WebSSH录像实现
    Asciinema文章勘误及Web端使用介绍
    Asciinema:你的所有操作都将被录制
    Django实现WebSSH操作物理机或虚拟机
  • 原文地址:https://www.cnblogs.com/leo-chen-2014/p/3751173.html
Copyright © 2011-2022 走看看