二分查找(JAVA)

思路

二分查找也是前人研究很久后总结出来的,不必因为自己想不到而感到难过。
二分查找有个大前提:待查询的数组必须是有序的,这里以升序为例。
其思路很好理解,获取位于数组中间的值,与被查找值比较,因为数组的有序性,可以缩小查找的范围。这样一直这么查找,直到找到该值,或找不到。
类似小时候玩儿的一个猜数字游戏。卡片里写了一个从0~100的数字,开始猜它是多少。
先猜是50,被告知,比这个大。于是范围缩小为51~100
再猜是75,被告知,比这个小。于是范围缩小为51~76
再猜是63,被告知,比这个小。于是范围缩小为51~62
再猜是56,被告知,回答正确。
可以用递归实现

递归实现

定义一个方法

public int binarySearch(int[] array, int left, int right, int value) {
	if(left > right) {
		return -1;
	}
	int mid = left + ((right-left)>>1);
	if (array[mid] == value) {
		return mid;
	} else if (array[mid] > value) {
		return binarySearch(array, left, mid - 1, value);
	} else {
		return binarySearch(array, mid + 1, right, value);
	}
}

对外的方法

public int binarySearch(int[] array, int value) {
	return binarySearch(array, 0, array.length, value);
}

循环实现

public int binarySearch(int[] array, int value) {
	int low = 0;
	int high = array.length - 1;
	while (low <= high) {
		int mid = low + ((high - low) >> 1);
		if (array[mid] == value) {
			return mid;
		} else if (array[mid] > value) {
			high = mid - 1;
		} else {
			low = mid + 1;
		}
	}
	return -1;
}

比较有趣的是下边这些实现

有序的数组中很有可能会有重复的元素,于是有了如下的问题

  1. 查找第一个等于指定值的元素索引
  2. 查找最后一个等于指定值的元素索引
  3. 查找第一个大于等于指定值的元素索引
  4. 查找最后一个小于等于给定值的元素索引

查找第一个等于指定值的元素索引

思路

原二分查找在找到一个元素后,检查与上一个元素是否相等
如果不相等,当前元素就是第一个
如果相等,相当于没找到目标元素,继续往前找,high = mid - 1

代码实现

public int binarySearch(int[] array, int value) {
	int low = 0;
	int high = array.length - 1;
	while (low <= high) {
		int mid = low + ((high - low) >> 1);
		if (array[mid] == value) {
			if(mid == 0 || array[mid-1] != value) {
				return mid;
			} else {
				high = mid - 1;
			}
		} else if (array[mid] > value) {
			high = mid - 1;
		} else {
			low = mid + 1;
		}
	}
	return -1;
}

查找最后一个等于指定值的元素索引

思路

原二分查找在找到一个元素后,检查与下一个元素是否相等
如果不相等,当前元素就是最后一个
如果相等,相当于没找到目标元素,继续往后找,low= mid + 1

代码实现

public int binarySearch(int[] array, int value) {
	int low = 0;
	int high = array.length - 1;
	while (low <= high) {
		int mid = low + ((high - low) >> 1);
		if (array[mid] == value) {
			if(mid == array - 1 || array[mid+1] != value) {
				return mid;
			} else {
				low = mid + 1;
			}
		} else if (array[mid] > value) {
			high = mid - 1;
		} else {
			low = mid + 1;
		}
	}
	return -1;
}

查找第一个大于等于指定值的元素索引

思路

原二分查找要变一下,因为这时可以合并大于和等于的情形了。相当于找一个大于等于指定值的元素索引(当然,判定下length-1位置的元素是否比要查找的元素大,有了就返回,没有就返回-1,不过别闹)

while (low <= high) {
	int mid = low + ((high - low) >> 1);
	if (array[mid] >= value) {
		return mid;
	} else {
		low = mid + 1;
	}
}

接着就和查找第一个等于指定值的元素索引类似了
检查上一个元素是否也大于等于指定值
如果不大于等于,当前元素就是第一个满足要求的元素
如果大于等于,相当于没找到目标元素,继续往前找,high = mid - 1

代码实现

public int binarySearch(int[] array, int value) {
	int low = 0;
	int high = array.length - 1;
	while (low <= high) {
		int mid = low + ((high - low) >> 1);
		if (array[mid] >= value) {
			if(mid == 0 || array[mid-1] < value) {
				return mid;
			} else {
				high = mid - 1;
			}
		} else {
			low = mid + 1;
		}
	}
	return -1;
}

查找最后一个小于等于给定值的元素索引

思路

原二分查找要变一下,因为这时可以合并小于和等于的情形了。相当于找一个小于等于指定值的元素索引(也别闹)

while (low <= high) {
	int mid = low + ((high - low) >> 1);
	if (array[mid] <= value) {
		return mid;
	} else {
		high = mid - 1;
	}
}

接着就和查找最后一个等于指定值的元素索引类似了
检查下一个元素是否也小于等于指定值
如果不小于等于,当前元素就是最后一个满足要求的元素
如果小于等于,相当于没找到目标元素,继续往后找,low = mid + 1

代码实现

public int binarySearch(int[] array, int value) {
	int low = 0;
	int high = array.length - 1;
	while (low <= high) {
		int mid = low + ((high - low) >> 1);
		if (array[mid] <= value) {
			if(mid == array.length - 1 || array[mid+1] > value) {
				return mid;
			} else {
				low = mid + 1;
			}
		} else {
			high = mid - 1;
		}
	}
	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值