《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及解释。
数组的旋转类似于二进制操作的循环右移或循环左移,左移或右移出的数又再次加入到数组的右边或左边。数组
{
1
,
2
,
3
,
4
}
\{1,2,3,4\}
{1,2,3,4}旋转一位为数组
{
4
,
1
,
2
,
3
}
\{4,1,2,3\}
{4,1,2,3}(右移)或数组
{
2
,
3
,
4
,
1
}
\{2,3,4,1\}
{2,3,4,1}(左移)。如果有序的数组没有经过旋转则可以通过二分搜索进行搜索指定的元素,但是现在有序的数组已经经过了多次的旋转,情况就变得有点复杂了。
算法根据数组中中间元素与数组最左边的元素的值得比较来分别进行相应的操作。
int rotateArraySearch(int *a,int left,int right,int x)
{
int mid = (left + right) / 2;
if (x == a[mid])
return mid;
if (right < left)
return -1;
//这时数组的左边是有序的
if (a[left] < a[mid])
{
//X位于数组的左边
if ((x >= a[left]) && (x < a[mid]))
{
return rotateArraySearch(a, left, mid-1, x);
}
//X位于数组的右边
else
{
return rotateArraySearch(a, mid+1, right, x);
}
}
//这时数组的右边是有序的
else if (a[mid] < a[left])
{
//X位于数组的右边
if ((x > a[mid]) && (x <= a[right]))
{
return rotateArraySearch(a, mid + 1, right, x);
}
//X位于数组的左边
else
{
return rotateArraySearch(a, left, mid - 1, x);
}
}
else if (a[left] == a[mid])
{
//这时数组的右边是有序的
if (a[mid]!= a[right])
{
return rotateArraySearch(a, mid + 1, right, x);
}
//这时无法确定那一边是有序的
else
{
int result= rotateArraySearch(a, left, mid - 1, x);
if (result == -1)
{
return rotateArraySearch(a, mid + 1, right, x);
}
else
{
return result;
}
}
}
return -1;
}