参考程序
1.常规算法,复杂度为O(N):
double Power(double x, unsigned int N)
{
double result = 1.0;
for (unsigned int i=0; i<N; i++)
result *= x;
return result;
}
折半算法(二分法),复杂度为O(logN):
double Power(double x, unsigned int N)
{
if (N == 0)
return 1.0;
double t = Power(x, N/2);
if (N % 2 == 0)
return t * t;
else
return t * t * x;
}
2.算法分析:在讲解枚举法时,我们讨论了如何用枚举法求解此题,但如果求解的精度进一步提高,使用枚举法就无能为力了,在此我们再一次讨论如何用二分法求解此题。
由题意知(i,i+1)中若有根,则只有一个根,我们枚举根的值域中的每一个整数x(-100≤x≤100),设定搜索区间[x1,x2],其中x1=x,x2=x+1。若:
⑴f(x1)=0,则确定x1为f(x)的根;
⑵f(x1)*f(x2)<0,则确定根x在区间[x1,x2]内。
⑶f(x1)*f(x2)>0,则确定根x不在区间[x1,x2]内,设定[x2,x2+1]为下一个搜索区间;
若确定根x在区间[x1,x2]内,采用二分法,将区间[x1,x2]分成左右两个子区间:
左子区间[x1,x]和右子区间[x,x2](其中x=(x1+x2)/2)。如果f(x1)*f(x)≤0,
则确定根在左区间[x1,x]内,将x设为该区间的右界值(x2=x),继续对左区间进行对分;
否则确定根在右区间[x,x2]内,将x设为该区间的左界值(x1=x),继续对右区间进行对分;
上述对分过程一直进行到区间的间距满足精度要求为止(即x2-x1<0.000005)。此时确定x1为f(x)的根。
#include<stdio.h>
#include<stdlib.h>
void Function(double xa[], double a, double b, double c, double d, double left, double right, double e);//解方程
double F(double a, double b, double c, double d, double x);//函数表达式
int main()
{
double low = -100, high = 100;
double e = 0.000005;
double a = 1, b = -5, c = -4, d = 20;
double x[8] = {0};
printf("%f %f %f %f\n", a, b, c, d);
Function(x, a, b, c, d, low, high, e);//解方程
printf("%.5f %.5f %.5f\n", x[0], x[1], x[2]);
system("pause");
return 0;
}
double F(double a, double b, double c, double d, double x)//函数表达式
{
return ((a * x + b) * x + c) * x + d;
}
void Function(double xa[], double a, double b, double c, double d, double left, double right, double e)
{
double low, high, mid, i;
int top = 0;
for (i=left; i<right; i+=1)
{
low = i;
high = low + 1;
while ((high-low) >= e)
{
mid = (low + high) / 2;
if (F(a, b, c, d, mid) == 0)
{
xa[top++] = mid;
break;
}
if (F(a, b, c, d, low)*F(a, b, c, d, mid) <= 0)
high = mid;
else if (F(a, b, c, d, mid)*F(a, b, c, d, high) <= 0)
low = mid;
else
break;
}
if ((high-low) < e)
xa[top++] = low;
if (top > 1 && abs(xa[top-1] - xa[top-2]) < e)//消除重复的解
top--;
}
}
3.分成两组:
#include<stdio.h>
int count = 0;
int FalseCoin(int a[], int left, int right);
int main()
{
int a[60] = {0};
int i, n = 15;
for (i=0; i<=n; i++)
{
count = 0;
a[i] = -1;
printf("n = %d, count = %d\n", FalseCoin(a, 0, n), count);
a[i] = 0;
}
getchar();
return 0;
}
/*
函数功能:找出伪币,并返回其下标,若无伪币则返回-1。此算法适用于任何情况,且伪币越靠前,越容易找到
输入变量: int a[], 数组a中存储各硬币的重量
int left, 数组a的左边界
int right, 数组a的右边界
输出变量:无
返回值: int,伪币下标,若无伪币则返回-1
*/
int FalseCoin(int a[], int left, int right)
{
int mid = (left + right) / 2;
int num;
if (left >= right)//如果只有一枚硬币,无法找出伪币,相当于无伪币
{
count++;
return -1;
}
if ((right-left) == 1)//只有两枚硬币,轻者为伪币,等重则无伪币
{
count++;
return (a[left] < a[right]) ? left : (a[left] > a[right]) ? right : -1;
}
if ((right-left) == 2)//如果只有三枚硬币,轻者为伪币,等重则无伪币
{
count++;
if (a[left] < a[left+1])
return left;
else if (a[left] > a[left+1])
return left + 1;
else if (a[right] < a[left])
return right;
else
return -1;
}
//多余三枚硬币,将数组分成两半,分而治之
num = FalseCoin(a, left, mid);
if (num != -1)//找到伪币,直接返回
return num;
else //否则查找另一半
return FalseCoin(a, mid+1, right);
}
分成4组:
int FalseCoin(int a[], int len, int left, int right)
{
int left1, right1, left2, right2, left3, right3, left4, right4;
int sum1, sum2, sum3, sum4;
int q, i;
if (left > right)//如果子数组没有硬币
{
return -1;
}
if (right == left)//如果子数组只有一枚硬币,将其与相邻的硬币比较
{
if (left > 0)
return (a[left]<a[left-1]) ? left : (a[left]>a[left-1]) ? left-1 : -1;
if (right < len-1)
return (a[right]<a[right+1]) ? right : (a[right]>a[right+1]) ? right-1 : -1;
return -1;
}
if ((right-left) == 1)//只有两枚硬币,轻者为伪币,等重则无伪币
{
count++;
return (a[left] < a[right]) ? left : (a[left] > a[right]) ? right : -1;
}
if ((right-left) == 2)//如果只有三枚硬币,轻者为伪币,等重则无伪币
{
count++;
if (a[left] < a[left+1])
return left;
else if (a[left] > a[left+1])
return left + 1;
else if (a[right] < a[left])
return right;
else
return -1;
}
//将硬币分成4等份,若硬币总数不是4的倍数,则把另外不足4个的硬币先放在一边
q = (right - left + 1) / 4;
left1 = left;
right1 = left1 + q - 1;
left2 = right1 + 1;
right2 = left2 + q - 1;
left3 = right2 + 1;
right3 = left3 + q - 1;
left4 = right3 + 1;
right4 = left4 + q - 1;
//累计每组硬币的重量
sum1 = sum2 = sum3 = sum4 = 0;
for (i=left1; i<=right1; i++)
sum1 += a[i];
for (i=left2; i<=right2; i++)
sum2 += a[i];
for (i=left3; i<=right3; i++)
sum3 += a[i];
for (i=left4; i<=right4; i++)
sum4 += a[i];
//将硬币两两比较
count++;
if (sum1 != sum2)//伪币在第1,2组硬币中
{
if (sum1 < sum2)
return FalseCoin(a, len, left1, right1);
else
return FalseCoin(a, len, left2, right2);
}
count++;
if (sum3 != sum4) //伪币在第3,4组硬币中
{
if (sum3 < sum4)
return FalseCoin(a, len, left3, right3);
else
return FalseCoin(a, len, left4, right4);
}
return FalseCoin(a, len, right4+1, right);//等重,伪币在剩余的硬币中
}
评论