问题描述:
有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现
例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。
算法实现的基本思路:
找到负数和正数的分界点,如果正好是0就是它了,如果是正数,再和左面相邻的负数绝对值比较,如果是负数,取取绝对值与右面正数比较。还要考虑数组只有正数或负数的情况。
package JBArray;
public class GetMinAbsoluteValue {
/**
* 三种情况: 1、有正负数 2、只有正数 3、只有负数
*
* 找到正负数临界点,比较绝对值大小即可
*/
private 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 + (begin + end) / 2;// 计算当前的索引
if (a[mid] == 0) { //如果值为0,就是绝对值最小的值
return 0;
} else if (a[mid] > 0) { //如果值大于0,在左半部分查找
if (a[mid - 1] > 0)
end = mid - 1; //移一位大于0,结束下标变为mid-1
else if (a[mid - 1] == 0)
return 0; //移一位等于0,就是绝对值最小的值
else
break; //没找到
} else { //如果值小于0,在右半部分查找
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])) //大于0,和前面的一个数比较
absMin = a[mid];
else
absMin = a[mid - 1];
} else {
if (a[mid] < Math.abs(a[mid + 1]))//小于0,和后面的一个数比较
absMin = a[mid];
else
absMin = a[mid + 1];
}
return absMin;
}
public static void main(String[] args) {
int[] a1 = { -10, -5, -2, 7, 15, 50 };
int[] a2 = { 2, 4, 6, 7, 8 };
int[] a3 = { -13, -9, -6, -4, -3 };
int value = getMinAbsoluteValue(a1);
System.out.println(value);
int value1 = getMinAbsoluteValue(a2);
System.out.println(value1);
int value2 = getMinAbsoluteValue(a3);
System.out.println(value2);
}
}