题目:
算法思想:
有logn 就得往二分的方向想,由于不知道数组的大小,也不知道有几个整数,从第一个元素开始查找x,以指数级的向后搜索,每次步长变为原来的两倍如果出现x<2^i,则从2^(i-1) 和2^i之间利用二分查找的方法查找x,如果a[2^i>n]>=Inf 则查找失败返回-1,返回查找到的位置,如果查找失败则返回-1 。
const int Inf = 0x7fffffff;
int search(int *a, int x, int n) //指数级的查找
{
int t, i;
if (a[0] > x) //第0个元素大于x则查找失败
{
return -1;
}
else if (a[0] == x) //第0个元素等于x,返回0
{
return 0;
}
else //指数查找
{
t = a[1];
i = 1;
while (t < x)
{
i *= 2;
if (a[i] >= Inf)
{
return -1;
}
t = a[i];
}
}
return i;
}
int binsearch(int *a, int x, int l, int r) //二分查找
{
int m = l + (r - l) / 2;
if (l > r)
{
return -1;
}
if (x == a[m])
{
return m;
}
else if (x < a[m])
{
return binsearch(a, x, l, m - 1);
}
else
{
return binsearch(a, x, m + 1, r);
}
}
int main()
{
int l = 1000000;
int *a = new int[l];
srand(time(NULL));
int n = rand();
int i;
for (i = 0; i < n; i++)
{
a[i] = rand();
}
for (i = n; i < l; i++)
{
a[i] = Inf;
}
sort(a, a + n); //将前n个数排序,形成原始数据
int x;
cin >> x;
int r = search(a, x, n);
if (r == -1)
{
cout << "Out Of Range Of Array!" << endl;
}
else
{
int pos = binsearch(a, x, 2 ^ (r - 1), 2 ^ r);
if (pos != -1)
{
cout << "Position:" << i << endl;
}
else
{
cout << "Can't Find!" << endl;
}
}
return 0;
}
基本思路:采用类似二分查找的方法。首先依次搜索数组元素序列:A[1]、A[2]、A[2^2]、…、A[2^i]、…、A[2^k],直至到达一个元素值大于x(A[2^k]>x)或元素值等于x(A[2^k]=x)的数组元素位置。若找到了等于x的数组元素,则问题得解;否则继续在数组区间[2^(k-1),2^k]内进行二分搜索。算法基本过程描述如下:
find (A[], x)
pos = 1
while (A[pos] < x)
pos = 2 * pos
if (A[pos]==x)
return pos;
return binary-search(A[pos/2..pos], x);
显然,上述算法中的初始搜索过程的结束位置值2k,或者2k <n,或者。因而比较的次数一定是O(logn)。接下来在数组区间[2k-1,2k]内的二分搜索过程需要花费时间O(log(2k -2k-1))= O(logn)。因此,整个算法的时间复杂度为O(logn)。