《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及解释。
普通算法利用数组有序以及二分查找的思想。当中间值
a
r
r
a
y
[
m
i
d
]
array[mid]
array[mid]小于中间值索引
m
i
d
mid
mid时中间值左边的元素的最大值为
m
i
d
−
2
mid-2
mid−2且元素值单调递减,中间值左边的元素的索引值从
m
i
d
−
1
mid-1
mid−1以1位单位单调递减,因此在左边不可能出现魔术索引。此时递归搜索右边。当中间值
a
r
r
a
y
[
m
i
d
]
array[mid]
array[mid]大于中间值索引
m
i
d
mid
mid时中间值右边的元素的最小值为
m
i
d
+
2
mid+2
mid+2且元素值单调递增,中间值右边的元素的索引值从
m
i
d
+
1
mid+1
mid+1以1位单位单调递增,因此在右边不可能出现魔术索引。此时递归搜索左边。如果中间值等于中间索引则返回,这里只要求求一个魔术索引,但是其实数组中也可以有多个魔术索引。
改进算法考虑了数组中有相同元素值的情况,这时就无法排除某一边而是要两边同时搜索,但是可以减少搜索的范围。
//假设数组中各个元素的值不同(普通算法)
int magicFast(vector<int> &array,int start,int end)
{
if (end < start)
return -1;
int mid = (start + end) / 2;
if (array[mid] == mid)
{
return mid;
}
else if (array[mid] > mid)
{
return magicFast(array, start, mid-1);
}
else
{
return magicFast(array, mid=1, end);
}
}
int magicFast(vector<int> array)
{
return magicFast(array,0,array.size()-1);
}
//这里考虑了数组中有相同元素值的情况(改进算法)
int max(int a,int b)
{
if (a > b)
return a;
else
return b;
}
int min(int a, int b)
{
if (a > b)
return b;
else
return a;
}
int magicFast(vector<int> &array,int start,int end)
{
if (end < start)
return -1;
int midIndex = (start + end) / 2;
int midValue = array[midIndex];
if (midValue == midIndex)
{
return midIndex;
}
int leftIndex = min(midIndex-1,midValue);
int left= magicFast(array, start, leftIndex);
if (left>=0)
{
return left;
}
int rightIndex = max(midIndex + 1, midValue);
int right = magicFast(array, rightIndex, end);
return right;
}
int magicFast(vector<int> array)
{
return magicFast(array,0,array.size()-1);
}