二分查找(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;
}
二分查找(Binary Search)是一种在有序组中查找某一特定元素的搜索算法。其基本思想是:每次取组中间的元素与目标值进行比较,如果中间元素等于目标值,则查找成功;如果中间元素大于目标值,则在组左半部分继续查找;如果中间元素小于目标值,则在组右半部分继续查找。重复以上步骤,直到找到目标值或确定没有目标值为止。 以下是二分查找Java实现: ``` public static int binarySearch(int[] arr, int target) { int left = 0; int right = arr.length - 1; while (left <= right) { int mid = (left + right) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; // 表示未找到目标元素 } ``` 在上述代码中,我们定义了一个 `binarySearch` 方法,该方法接收两个参,一个是有序组 `arr`,另一个是目标值 `target`。首先,我们定义两个指针 `left` 和 `right`,分别指向组的左端和右端。然后,我们进入循环,每次计算中间元素的下标 `mid`,并判断中间元素与目标值的大小关系。如果中间元素等于目标值,则查找成功,返回其下标;如果中间元素小于目标值,则在组右半部分继续查找,将 `left` 指针指向 `mid + 1`;如果中间元素大于目标值,则在组左半部分继续查找,将 `right` 指针指向 `mid - 1`。最后,如果循环结束仍未找到目标元素,则返回 `-1`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值