每週算法html
一ios
很高興每週算法專題終於能夠和你們見面,每週算法專題一週更新一次,每次五個算法,算法有難有易,算法均來源於各類經典的算法題以及各大公司招聘時的筆試面試題,咱們的目標在於算法的探討,尋找更好的解決方案,儘可能作到每個算法都給出從易到難的解題過程,從而使本身磨練出一套解決問題的思路,以及遇到新問題時該如何尋找解決方法。面試
在此給出了本週相應的算法以及源碼,視屏教程能夠到此觀看算法
http://edu.51cto.com/course/course_id-5071.html 編程
一、 最大公約數數組
<1> 題目描述:求解兩個整數(不能是負數)的最大公約數(要求兩數不能同時爲0)ide
<2> 方法一:窮舉法函數
<3> 方法二:相減法spa
<4> 方法三:歐幾里德展轉相除法htm
<5> 方法四:歐幾里德展轉相除法 遞歸實現
二、 最小公倍數
<1> 題目描述:求解兩個整數(不能是負數)的最小公倍數
<2> 方法一:窮舉法
<3> 方法二:公式lcm = a * b / gcd(a,b)
三、 二進制中1的個數<本題感謝 編程之美 的提供>
<1> 題目描述:對一個字節的無符號×××變量,求二進制數中1的個數
(要求:執行效率儘量高)
<2> 方法一:使用模方法
<3> 方法二:使用位操做運算
<4> 方法三:時間複雜度是與1的個數有關的算法
<5> 方法四:分支法
<6> 方法五:查表法
四、 高效進制轉換
<1> 題目描述:對一個 unsigned long 的整數,將其轉換爲對應的16進制數
<2> 方法一:使用數組存儲數據
<3> 方法二:使用棧存儲數據
<4> 方法三:使用字符串常量高效轉換
五、 位設置(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;
}
二、 相減法
#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;
}
三、 歐幾里德展轉相除法
#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;
}
四、 歐幾里德展轉相除法 遞歸實現
#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;
}
2、最小公倍數
一、 窮舉法
#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;
}
3、二進制中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;
}
二、 使用位操做運算
#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;
}
三、 時間複雜度是與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;
}
四、 分支法
#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;
}
五、 查表法
#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;
}
4、進制轉換
一、 使用數組存儲數據
#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;
}
二、 使用棧存儲數據
#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;
}
5、位設置(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;
}
二、 位操做設置法
#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;
}