定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小;如果 arr[N-1]<arr[N-2],那么arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1],又有arr[i]<arr[i+1],那么arr[i]是局部最小。给定无序数组arr,已知arr中任意两个相邻的数都不相等。写一个函数,只需返回arr中任意一个局部最小出现的位置即可
局部最小的概念和极小值是一样的,先判断边界,如果arr[0]的值比arr[1]小,arr[n-1]的值比arr[n-2]小,则arr[0]和arr[n-1]也是局部最小。
如果上面两种都不满足,则arr[0]和arr[n-1]之间必然存在一个局部最小点,因为arr[0]-arr[1]是下降趋势,arr[n-2]-arr[n-1]是上升趋势,所以数组中间肯定会有一个转折点。如何快速的找:二分,,,假设中间的值为B,B左边的值为A,B右边的值为C,如果ABC满足局部最小则返回B,如果ABC是上升的趋势,则在0-A区域二分,如果ABC是下降的趋势,则在C-n-1区域二分,依次二分下去会很快找到局部最小
代码实现
public class FindOneLessValueIndex {
public static int getLessIndex(int[] arr) {
if (arr == null || arr.length == 0) {
return -1; // no exist
}
if (arr.length == 1 || arr[0] < arr[1]) {
return 0;
}
if (arr[arr.length - 1] < arr[arr.length - 2]) {
return arr.length - 1;
}
int left = 1;
int right = arr.length - 2;
int mid = 0;
while (left < right) {
mid = (left + right) / 2;
if (arr[mid] > arr[mid - 1]) {
right = mid - 1;
} else if (arr[mid] > arr[mid + 1]) {
left = mid + 1;
} else {
return mid;
}
}
return left;
}public static void printArray(int[] arr) {
for (int i = 0; i != arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}public static void main(String[] args) {
int[] arr = { 6, 5, 3, 4, 6, 7, 8 };
printArray(arr);
int index = getLessIndex(arr);
System.out.println("index: " + index + ", value: " + arr[index]);}
}