折半查找习题解答

1、本节的折半查找算法有一个特点:如果待查找的元素在数组中有多个则返回其中任意一个,以本节定义的数组int a[8] = { 1, 2, 2, 2, 5, 6, 8, 9 };为例,如果调用binarysearch(2)则返回3,即a[3],而有些场合下要求这样的查找返回a[1],也就是说,如果待查找的元素在数组中有多个则返回第一个。请修改折半查找算法实现这一特性。

//By LYLtim

#include<stdio.h>

#define LEN 8
int a[LEN] = { 1, 2, 2, 2, 5, 6, 8, 9 };

int Search(int k)
{
	int start = 0, end = LEN -1;
	while (start <= end) {
		int mid = (start + end) >> 1;
		if (k < a[mid])
		    end = mid -1;
		else if (k > a[mid])
		    start = mid +1;
		else {
			while (a[mid-1] == a[mid]) mid -= 1;
			return mid;
		}
	}
	return -1;
}
		

int main(void)
{
	printf("%d\n",Search(2));
	return 0;
}

 

2、编写一个函数double mysqrt(double y);y的正平方根,参数y是正实数。我们用折半查找来找这个平方根,在从0到y之间必定有一个取值是y的平方根,如果我们查找的数xy的平方根小,则x2<y,如果我们查找的数xy的平方根大,则x2>y,我们可以据此缩小查找范围,当我们查找的数足够准确时(比如满足|x2-y|<0.001),就可以认为找到了y的平方根。

//By LYLtim
double mysqrt(double y)
{
	double l = 0, r = y, x;
	while (r - l > 0.000001) {
		x = (l + r) / 2;
		if (x * x > y) r = x;
		else l = x;
	}
	return (l + r) / 2;
}

 

3、编写一个函数double mypow(double x, int n);xn次方,参数n是正整数。最简单的算法是:

double product = 1;
for (i = 0; i < n; i++)
	product *= x;

这个算法的时间复杂度是Θ(n)。其实有更好的办法,比如mypow(x, 8),第一次循环算出x·x=x2,第二次循环算出x2·x2=x4,第三次循环算出4·x4=x8。这样只需要三次循环,时间复杂度是Θ(lgn)。思考一下如果n不是2的整数次幂应该怎么处理。

 1 // 递归版 By LYLtim
 2 double mypow(double x, int n)
 3 {
 4     if (n == 1) return x;
 5     else {
 6         double tmp = mypow(x, n >> 1);
 7         tmp *= tmp;
 8         if (n & 1)
 9             return tmp * x;
10         else
11             return tmp;
12     }
13 }
 1 // 非递归版 By LYLtim 
 2 double mypow(double x, int n){
 3     double s = 1;
 4     while (n) {
 5         if (n & 1) s *= x;
 6         x *= x;
 7         n >>= 1;
 8     }
 9     return s;
10 }

 

posted @ 2011-11-09 16:40  LYLtim  阅读(988)  评论(0编辑  收藏  举报