面试题: 一个有序数组A[n],从中间某一点截断, 把它前半部分接到后半部分的后面形成B[n], 请从B[n]找到A[n]截断位置
分析:
1. 这个数组A必须是有序的, 有序就必须考虑两种情况升序和降序. 假设所有都平序, 应该不满足需要. 比如全为1
2. 这个找到截断的位置,应该可以用二分法来做
3. 数组的个数应该必须大于等于2. 2个数的数组是可以的. 比如3,4.从4处截断可以形成4,3
从测试来说, 我们可以考虑以下例子:
1. 只有1个数的数组
2. 只有2个数的数组
3. 只有一个转折的数组(升序)
4. 只有一个转折的数组(降序)
5. 不止一个转折的数组
6. 全升的数组
7. 全降的数组
8. 只有一个转折的数组,转折点左右重复数
9. 只有一个转折的数组,非转折点有重复数
如何判断数组A是升序还是降序呢? 其实 只要判断第一个数和最后一个数的大小就可以了. 如果首数大于或等于最后数, 原数组就是升序. 否则降序
不说了,上程序 (C#):
public static int FindIndexFromArray(int[] bArray)
{
//Detect if A[n] is ASC or DSC order
bool isAscOrder = bArray[0] >= bArray[bArray.Length - 1];
//Use Binary Search
int low = 0;
int high = bArray.Length - 1;
int mid = -1;
while (true)
{
if ((low + high) / 2 != mid)
{
mid = (low + high) / 2;
if (isAscOrder && bArray[low] <= bArray[mid]
||
!isAscOrder && bArray[low] >= bArray[mid]
)
{
low = mid;
}
if (isAscOrder && bArray[mid] <= bArray[high]
||
!isAscOrder && bArray[mid] >= bArray[high]
)
{
high = mid;
}
if (low + 1 == high)
{
break;
}
}
else
{
throw new ArgumentException("The provided array did not match the rule. Please check!");
}
}
return bArray.Length - low - 2;
}
测试程序: 从数组A构造数组B
public static int[] ConstructArrayB(int[] aArray, int index)
{
if (aArray.Length < 2 || index > aArray.Length - 2)
{
throw new ArgumentException();
}
int[] bArrary = new int[aArray.Length];
for (int i = 0; i <= index; i++)
{
bArrary[i - index + aArray.Length - 1] = aArray[i];
}
for (int i = index + 1; i < aArray.Length; i++)
{
bArrary[i - index - 1] = aArray[i];
}
return bArrary;
}
public static void Print(int[] array)
{
foreach (int c in array)
{
Console.Write(c + " ");
}
Console.WriteLine();
}
static void Main(string[] args)
{
int[] a = { 1, 1, 2, 3, 3, 4,5,12,30 };
Console.WriteLine("数组A");
Print(a);
int index = 2;
Console.WriteLine("从{0}折断数组A", index);
int[] b = ConstructArrayB(a, index);
Console.WriteLine("数组B:");
Print(b);
int index2 = FindIndexFromArray(b);
Console.Write("从数组B得到A的折断点:{0}", index2);
Console.Write("判断算法正确与否:{0}", index == index2 );
}
最近 再次想了想, 中间程序 可以简化
public static int FindIndexFromArray(int[] bArray)
{
//Detect if A[n] is ASC or DSC order
bool isAscOrder = bArray[0] >= bArray[bArray.Length - 1];
//Use Binary Search
int low = 0;
int high = bArray.Length - 1;
int mid = -1;
while (low <= high)
{
mid = (low + high) / 2;
if (isAscOrder && bArray[mid] > bArray[mid + 1]
||
!isAscOrder && bArray[mid] < bArray[mid + 1]
)
{
return bArray.Length - mid - 2;
}
if (isAscOrder && bArray[mid] <= bArray[high]
||
!isAscOrder && bArray[mid] <= bArray[high]
)
{
high = mid;
}
else
{
low = mid;
}
}
return bArray.Length - mid - 2;
}