找出有序数组中绝对值最小的数

假设数组是从小到大排序,数值可能为负数、0、正数。

思路一

可以一次性遍历一遍,找出绝对值最小值,此时时间复杂度为O(N),缺点是没有利用数组是有序的这一特点。

int getMinAbs(int[] num){
	//当数组只有一个元素的情况直接返回
	if(num.length == 1)
		return num[0];
	
	//当数组非负时直接返回num[0],当数组非正时直接返回num[num.length-1]
	if(num[0] >= 0)
		return num[0];
	else if(num[num.length-1] <= 0)
		return num[num.length-1];
	
	int min = Math.abs(num[0]);
	for(int i=1; i<num.length; i++)
		min = Math.min(min, Math.abs(num[i]));
	
	return min;
}

  

思路二

数组有序,可以利用二分查找的特性。中间的数是正数,往后找;中间的数是负数,往前找。

问题的本质是找到正数的最小值,或负数的最大值,分析以下集中情况

数组为a[], 数组大小为n.

  • n=1,没有商量的余地,直接返回
  • a[0] * a[n-1] >= 0,说明这些元素同为非正或同为非负。要是a[0]>=0,返回a[0];否则返回a[n-1]
  • a[0] * a[n-1] < 0,说明这些元素中既有整数,也有负数。此时需要计算中间位置为mid = low + high/2,如果a[mid]*a[low] >=0说明a[mid]也为非正,缩小范围low=mid;如果a[mid]*a[high]>=0,说明a[mid]非负,缩小范围high=mid。在期间如果还有两个元素,那么就比较以下他俩,直接返回了
int getMinAbs(int[] num) {
	//当数组只有一个元素的情况直接返回
	if(num.length == 1)
		return num[0];
	
	//当数组非负时直接返回num[0],当数组非正时直接返回num[num.length-1]
	if(num[0] >= 0)
		return num[0];
	else if(num[num.length-1] <= 0)
		return num[num.length-1];
	
	//当数组有正有负时,返回最大的负数与最小的非负数中较小的那一个
	int low = 0, high = num.length-1, mid = (low + high)/2;
	while(low < high){
		if(num[mid] < 0)
			low = mid + 1;
		else if(num[mid] > 0){
			if(num[mid] * num[mid-1] < 0)
				return Math.min(Math.abs(num[mid-1]), num[mid]);
			high = mid - 1;
		}else 
			return num[mid];
		
		mid = (low + high) / 2;
	}
	
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/lightwindy/p/9576619.html
今日推荐