每周算法(一)

每周算法

     很高兴每周算法专题终于可以和大家见面,每周算法专题一周更新一次,每次五个算法,算法有难有易,算法均来源于各种经典的算法题以及各大公司招聘时的笔试面试题,我们的目标在于算法的探讨,寻找更好的解决方案,尽量做到每一个算法都给出从易到难的解题过程,从而使自己磨练出一套解决问题的思路,以及遇到新问题时该如何寻找解决方法。

     在此给出了本周相应的算法以及源码,视屏教程可以到此观看

     http://edu.51cto.com/course/course_id-5071.html


1、 最大公约数

<1> 题目描述:求解两个整数(不能是负数)的最大公约数(要求两数不能同时为0)

<2> 方法一:穷举法

<3> 方法二:相减法

<4> 方法三:欧几里德辗转相除法

<5> 方法四:欧几里德辗转相除法 递归实现

 

2、 最小公倍数

<1> 题目描述:求解两个整数(不能是负数)的最小公倍数

<2> 方法一:穷举法

<3> 方法二:公式lcm = a * b / gcd(a,b)

 

3、 二进制中1的个数<本题感谢 编程之美 的提供>

<1> 题目描述:对一个字节的无符号整形变量,求二进制数中1的个数

(要求:执行效率尽可能高)

  <2> 方法一:使用模方法

  <3> 方法二:使用位操作运算

  <4> 方法三:时间复杂度是与1的个数有关的算法

  <5> 方法四:分支法

  <6> 方法五:查表法

 

4、 高效进制转换

<1> 题目描述:对一个 unsigned long 的整数,将其转换为对应的16进制数

<2> 方法一:使用数组存储数据

<3> 方法二:使用栈存储数据

<4> 方法三:使用字符串常量高效转换

 

5、 位设置(bit_set

<1> 题目描述: 对一个unsigned char 8 bit数据的指定位置0或置1操作,并保持其他位不变。

       函数原型:voidbit_set(unsigned char *p_data, unsigned char position, bool flag);

     参数说明:p_data 是指定的原数据,position是指定位(取值范围1~8),flag表示是置0还是置1操作

<2> 方法一:分支设置法

<3> 方法二:位操作设置法

 

 

 

 

源码:

一、最大公约数

1、 穷举法

#include<iostream>

using namespacestd;

unsigned longGCD(unsigned long a, unsigned long b)

{

       if(a == 0)

              return b;

       else if(b == 0)

              return a;

    else if(a == b)

              return a;

       unsigned long gcd;

       gcd = a>b?b:a;

       while(gcd > 1)

       {

              if((a%gcd==0) &&(b%gcd==0))

                     return gcd;

              gcd--;

       }

       return gcd;

}

void main()

{

       unsigned long a,b;

       cout<<"请输入a b:>";

       cin>>a>>b;

       unsigned long gcd = GCD(a,b);

       cout<<"gcd ="<<gcd<<endl;

}

 

2、 相减法

#include<iostream>

using namespacestd;

unsigned longGCD(unsigned long a, unsigned long b)

{

       if(a == 0)

              return b;

       else if(b == 0)

              return a;

    else if(a == b)

              return a;

       unsigned long gcd;

       while(a != b)

       {

              gcd = a > b ? (a-=b) : (b-=a);

       }

       return gcd;

}

void main()

{

       unsigned long a,b;

       cout<<"请输入a b:>";

       cin>>a>>b;

       unsigned long gcd = GCD(a,b);

       cout<<"gcd ="<<gcd<<endl;

}

3、 欧几里德辗转相除法

#include<iostream>

using namespacestd;

unsigned longGCD(unsigned long a, unsigned long b)

{

       if(a == 0)

              return b;

       else if(b == 0)

              return a;

    else if(a == b)

              return a;

       unsigned long mod = a % b;

       while(mod != 0)

       {

              a = b;

              b = mod;

              mod = a % b;

       }

       return b;

}

void main()

{

       unsigned long a,b;

       cout<<"请输入a b:>";

       cin>>a>>b;

       unsigned long gcd = GCD(a,b);

       cout<<"gcd ="<<gcd<<endl;

}

4、 欧几里德辗转相除法 递归实现

#include<iostream>

using namespacestd;

unsigned longGCD(unsigned long a, unsigned long b)

{

       if(b == 0)

              return a;

       else

              return GCD(b, a%b);

}

void main()

{

       unsigned long a,b;

       cout<<"请输入a b:>";

       cin>>a>>b;

       unsigned long gcd = GCD(a,b);

       cout<<"gcd ="<<gcd<<endl;

}

 

二、最小公倍数

1、 穷举法

#include<iostream>

using namespacestd;

unsigned longLCM(unsigned long a, unsigned long b)

{

       if(a * b == 0)

              return 0;

       unsigned long lcm = a > b ? a : b;

       while(1)

       {

              if((lcm%a==0) &&(lcm%b==0))

                     break;           

              lcm++;

       }

       return lcm;

}

 

void main()

{

       unsigned long a,b;

       cout<<"请输入a b:>";

       cin>>a>>b;

 

       unsigned long lcm = LCM(a,b);

       cout<<"lcm ="<<lcm<<endl;

}

2、公式lcm = a * b / gcd(a,b)

#include<iostream>

using namespacestd;

unsigned longGCD(unsigned long a, unsigned long b)

{

       if(b == 0)

              return a;

       else

              return GCD(b, a%b);

}

unsigned longLCM(unsigned long a, unsigned long b)

{

       if(a * b == 0)

              return 0;

       return (a*b)/GCD(a,b);

}

 

void main()

{

       unsigned long a,b;

       cout<<"请输入a b:>";

       cin>>a>>b;

 

       unsigned long lcm = LCM(a,b);

       cout<<"lcm ="<<lcm<<endl;

}

 

三、二进制中1的个数

1、使用模方法

#include<iostream>

using namespacestd;

intCount(unsigned char v)

{

       int count = 0;

       while(v != 0)

       {

              if(v % 2 == 1)

                     count++;

              v /= 2;

       }

       return count;

}

void main()

{

       unsigned char ch = 255;

       int count = Count(ch);

       cout<<"count ="<<count<<endl;

}

2、 使用位操作运算

#include<iostream>

using namespacestd;

intCount(unsigned char v)

{

       int count = 0;

       while(v != 0)

       {

              count += v & 0x01;

              v >>= 1;

       }

       return count;

}

void main()

{

       unsigned char ch = 255;

       int count = Count(ch);

       cout<<"count ="<<count<<endl;

}

3、 时间复杂度是与1的个数有关的算法

#include<iostream>

using namespacestd;

intCount(unsigned char v)

{

       int count = 0;

       while(v != 0)

       {

              v &= (v-1);

              count++;

       }

       return count;

}

 

void main()

{

       unsigned char ch = 255;

       int count = Count(ch);

       cout<<"count ="<<count<<endl;

}

4、 分支法

#include<iostream>

using namespacestd;

intCount(unsigned char v)

{

     int count = 0;

     switch (v)

     {

          case 0x0:

               count = 0;

               break;

          case 0x1:

          case 0x2:

          case 0x4:

          case 0x8:

          case 0x10:

          case 0x20:

          case 0x40:

          case 0x80:

               count = 1;

               break;

          case 0x3:

          case 0x6:

          case 0xc:

          case 0x18:

          case 0x30:

          case 0x60:

          case 0xc0:

               count = 2;

               break;

               //...

         // [注意] 此处需要把代码补齐

      }

      return count;    

}

void main()

{

       unsigned char ch = 255;

       int count = Count(ch);

       cout<<"count ="<<count<<endl;

}

5、 查表法

#include<iostream>

using namespacestd;

intcountTable[256] =

{

     0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3,3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3,

        3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3,4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3,

        4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,

        3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3,4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3,

        4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4,4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6,

        6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4,

        5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,

        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3,

        4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5,5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4,

        4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6,7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6,

        7, 6, 7, 7, 8

};

intCount(unsigned char v)

{

     return countTable[v];

}

void main()

{

       unsigned char ch = 255;

       int count = Count(ch);

       cout<<"count ="<<count<<endl;

}

 

四、进制转换

1、 使用数组存储数据

#include<iostream>

using namespacestd;

char*Convert_16(unsigned long value)

{

       static char Buffer[sizeof(unsignedlong)*2+1];

       int mod;

       for(int i=sizeof(unsigned long)*2-1;i>=0; --i)

       {

              mod = value % 16;

              if(mod < 10)

              {

                     Buffer[i] = mod + '0';

              }

              else

              {

                     Buffer[i] = (mod-10) + 'A';

              }

              value /= 16;

       }

       return Buffer;

}

void main()

{

       unsigned long value = 4711;

       char *result = Convert_16(value);

       cout<<value<<" ="<<"0x"<<result<<endl;

}

2、 使用栈存储数据

#include<iostream>

#include<stack>

using namespacestd;

voidConvert_16(unsigned long value)

{

       stack<char> st;

       int mod;

       while(value != 0)

       {

              mod = value % 16;

              if(mod < 10)

              {

                     st.push(mod+'0');

              }

              else

              {

                     st.push((mod-10) + 'A');

              }

              value /= 16;

       }

       cout<<value<<" ="<<"0x";

       while(!st.empty())

       {

              cout<<st.top();

              st.pop();

       }

       cout<<endl;

}

void main()

{

       unsigned long value = 4711;

       Convert_16(value);

}

3、使用字符串常量高效转换

#include<iostream>

#include<stack>

using namespacestd;

char*Convert_16(unsigned long value)

{

       static char Buffer[sizeof(unsignedlong)*2+1];

       for(int i=sizeof(unsigned long)*2-1;i>=0; --i)

       {

              Buffer[i] ="0123456789ABCDEF"[value%16];

              value /= 16;

       }

       return Buffer;

}

void main()

{

       unsigned long value = 4711;

       char *result = Convert_16(value);

       cout<<value<<" ="<<"0x"<<result<<endl;

}

 

五、位设置(bit_set

1、分支设置法

#include<iostream>

using namespacestd;

voidbit_set(unsigned char *p_data, unsigned char position, bool flag)

{

      if(flag)//1

       {

              switch(position)

              {

              case 1:

                     *p_data |= 0x01;

                     break;

              case 2:

                     *p_data |= 0x02;

                     break;

              case 3:

                     *p_data |= 0x04;

                     break;

              case 4:

                     *p_data |= 0x04;

                     break;

              case 5:

                     *p_data |= 0x05;

                     break;

              case 6:

                     *p_data |= 0x06;

                     break;

              case 7:

                     *p_data |= 0x07;

                     break;

              case 8:

                     *p_data |= 0x08;

                     break;

              }

       }

       else //0

       {

              switch(position)

              {

              case 1:

                     *p_data &= 0x01;

                     break;

              case 2:

                     *p_data &= 0x02;

                     break;

              case 3:

                     *p_data &= 0x03;

                     break;

              case 4:

                     *p_data &= 0x04;

                     break;

              case 5:

                     *p_data &= 0x05;

                     break;

              case 6:

                     *p_data &= 0x06;

                     break;

              case 7:

                     *p_data &= 0x07;

                     break;

              case 8:

                     *p_data &= 0x08;

                     break;

              }

       }

}

void main()

{

       bool flag = true;

       //bool flag = false;

       unsigned char data = 'A';

       unsigned char position = 3;

       bit_set(&data,position,flag);

       cout<<data<<endl;

}

 

2、 位操作设置法

#include<iostream>

using namespacestd;

voidbit_set(unsigned char *p_data, unsigned char position, bool flag)

{

       unsigned char v = 0x01;

      if(flag)//1

       {

              *p_data |= (v<<(position-1));

       }

       else //0

       {

              *p_data &= ~(v<<(position-1));

       }

}

void main()

{

       bool flag = true;

       //bool flag = false;

       unsigned char data = 'A';

       unsigned char position = 3;

       bit_set(&data,position,flag);

       cout<<data<<endl;

}

你可能感兴趣的:(算法,算法基础,公约数)