题目:将一个有序数组arr[n]的前面一段arr[0…..k]移动到数组的末尾,找出新数组的最大值。比如:
int[] arr1 = {1, 5, 10, 20, 25, 30, 35, 50, 60, 70, 80, 100, 120, 150, 200};
int[] arr2 = {5, 10, 20, 25, 30, 35, 50, 60, 70, 80, 100, 120, 150, 200, 1};
int[] arr3 = {10, 20, 25, 30, 35, 50, 60, 70, 80, 100, 120, 150, 200, 1, 5};
int[] arr4 = {25, 30, 35, 50, 60, 70, 80, 100, 120, 150, 200, 1, 5, 10, 20};
int[] arr5 = {70, 80, 100, 120, 150, 200, 1, 5, 10, 20, 25, 30, 35, 50, 60};
int[] arr6 = {150, 200, 1, 5, 10, 20, 25, 30, 35, 50, 60, 70, 80, 100, 120};
arr1是一个有序数组,arr2~arr6是经过变化的新数组,找出新数组中的最大值.
这个题目比较简单最直接的方法就是一次比较,遍历整个数组,就找出最大的了,复杂度O(n)。
这里要讨论的是找出复杂度为O(logn)的实现。
1. 利用递归实现整个算法,大致的思想如下:
找到数组的中间位置mid的值, 将arr[mid]和数组的两端进行比较;如果arr[mid] 比两端的值都大,就将数组的前半段舍弃,后半部分进行递归;如果arr[mid]比某一点的值小,就将后半部分舍弃,将前半部分进行递归;直到限定范围内的数只有一个的时候,那么它就是最大值,返回。
- 非递归实现,由递归实现转换而来,代码如下:
/**
*查找部分有序数组的最大值
*/
public static int FindMaxOfArray(int[] arr){
int max = -1;
int i = 0, j = arr.length - 1, mid =(arr.length-1)/2;
while(j - i > 1){
//舍弃前半部分
if(arr[mid] > arr[i] && arr[mid] > arr[j]){
i = mid;
}
//舍弃后半部分
else if(arr[mid] < arr[i] && arr[mid] < arr[j]){
j = mid;
}
if(mid == (i+j)/2)
break;
mid = (i+j)/2;
}
if(arr[i] > arr[j])
max = arr[i];
else
max = arr[j];
return max;
}
上述代码中的 i , j 是数组的新的查找范围,直到 i 和 j 相邻时跳出,因为数组大小可能有奇数也可能为偶数, 所以最终保留i 和 j,其中较大的应该就是整个数组的最大值了。