问题描述:有一个升序排列的数组,数组中可能有正数、负数或0,求数组中元素的绝对值最小的数。例如,数组{-10, -5, -2, 7, 15, 50},绝对值最小的是-2
思路:如果数组中第一个元素为非负数,那么绝对值最小的数就是数组的第一个元素;如果数组的最后一个元素为负数,那么绝对值最小的数肯定是数组的最后一个元素;当数组中既有正数又有负数时,利用二分法来查找正数和负数的分界点的方法。其主要思路是:取数组中间位置的值a[mid]。
- a[mid] = 0,那么这个数就是绝对值最小的数;
- a[mid] > 0,如果a[mid - 1] < 0,那么就找到了分界点,通过比较a[mid]和a[mid - 1]的绝对值就可以找到数组中绝对值最小的数;如果a[mid - 1] = 0,那么a[mid - 1]就是要找的数,否则接着在数组的左半部分查找;
- a[mid] < 0,如果a[mid + 1] > 0,那么通过比较a[mid]和a[mid + 1]的绝对值即可,如果a[mid + 1] = 0,那么a[mid + 1]就是要找的数,否则接着在数组的右半部分继续查找
public class Test {
public static int getMinAbsoluteValue(int[] a) {
if (a == null)
return Integer.MIN_VALUE;
int len = a.length;
if (len < 1)
return Integer.MIN_VALUE;
// 数组中没有负数
if (a[0] >= 0)
return a[0];
// 数组中没有正数
if (a[len - 1] <= 0)
return a[len - 1];
int mid = 0;
int begin = 0;
int end = len - 1;
int absMin = 0;
// 数组中既有正数又有负数
while (true) {
mid = begin + (end - begin) / 2;
if (a[mid] == 0)
return 0;
else if (a[mid] > 0) {
if (a[mid - 1] > 0)
end = mid - 1;
else if (a[mid - 1] == 0)
return 0;
else
// 找到正负数的分界点
break;
}
else {
if (a[mid + 1] < 0)
begin = mid + 1;
else if (a[mid + 1] == 0)
return 0;
else
// 找到正负数的分界点
break;
}
}
// 获取正负数分界点处绝对值最小的值
if (a[mid] > 0) {
if (a[mid] < Math.abs(a[mid - 1]))
absMin = a[mid];
else
absMin = a[mid - 1];
}
else {
if (Math.abs(a[mid]) < a[mid + 1])
absMin = a[mid];
else
absMin = a[mid + 1];
}
return absMin;
}
}