天天看点

如何求绝对值最小的数

问题描述:

  有一个已经排序的数组(升序),数组中可能有正数、负数或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);
	}

}
           

继续阅读