第一章用了几个不同 求 最大公约数的例子 来引入算法分析与设计的概念
//欧几里得算法求最大公约数
//Input: m,n 非负不全为0的非负整数
//Output: m,n 的最大公约数
int gcdEuclid(int m, int n)
{
int r = 0;
while( 0 != n)
{
r = m%n;
m = n;
n = r;
}
return m;
}
//欧几里得算法求最大公约数
//Input: m,n 非负不全为0的非负整数
//Output: m,n 的最大公约数
int gcdEuclid(int m, int n)
{
//减法版本
while(0 != n)
{
//交换两数
if(m < n)
{
m = m + n;
n = m;
m = m - n;
}
m = m - n;
}
}
这是类似于蛮力法的例子
//连续减法求最大公约数
//Input: m,n 非负不全为0的非负整数
//Output: m,n 的最大公约数
int gcdContiSub(int m, int n)
{
int t = 0;
t = m < n ? m : n;
while(0 != t)
{
if(m%t == 0)
{
if(n%t == 0)
break;
}
t--;
}
return t;
}
然后是我们在中学学到的质数表求解,这个例子中要用到1~N的质数,于是引入了埃拉托色尼筛
//质数表求解
//Input: m,n 非负不全为0的非负整数
//Output: m,n 的最大公约数
int gcdHighScool(int m, int n)
{
vector<int> mPrime;
vector<int> nPrime;
EratosthenesSiece(mPrime, m);
EratosthenesSiece(nPrime, n);
vector<int> mPrimeFactors;
vector<int> nPrimeFactors;
//进行质因数分解
int mm = m;
for(int i=0; i < mPrime.size(); i++)
{
while(mm != mPrime[i])
{
if(mm % mPrime[i] == 0)
{
mPrimeFactors.push_back(mPrime[i]);
mm/=mPrime[i];
}
else
{
break;
}
}
}
mPrimeFactors.push_back(mm);
int nn = n;
for(int i=0; i < nPrime.size(); i++)
{
while(nn != nPrime[i])
{
if(nn % nPrime[i] == 0)
{
nPrimeFactors.push_back(nPrime[i]);
nn/=nPrime[i];
}
else
{
break;
}
}
}
nPrimeFactors.push_back(nn);
//质数表求解最大公约数 即中学所学的解法
int i=0,j=0,r=1;
int mPF = mPrimeFactors.size();
int nPF = nPrimeFactors.size();
while(true)
{
if(mPrimeFactors[i] == nPrimeFactors[j])
{
r *= mPrimeFactors[i];
if(i == mPF - 1 && j == mPF - 1)
break;
if(i < mPF - 1)
i++;
if(j < nPF - 1)
j++;
}else if(mPrimeFactors[i] > nPrimeFactors[j])
{
j++;
if(j >= nPF)
break;
}else
{
i++;
if(i >= mPF)
break;
}
}
return r;
}
//埃拉托色尼筛,求0-N的质数
void EratosthenesSiece(vector<int> &out, int n)
{
out.clear();
bool *isPrime = new bool[n];
memset(isPrime, true, sizeof(isPrime[0]*n));
for(int i=2; i<n; i++)
{
if(isPrime[i])
{
for(int j=i; i*j<n; j++)
{
isPrime[i*j] = false;
}
}
}
for(int i=2; i < n; i++)
{
if(isPrime[i])
{
out.push_back(i);
}
}
delete [] isPrime;
}