数据结构与算法(十一)—— 二分查找

有序数据集合中,查找某个值

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

说明: 

1. 循环条件 是 low <= high,而不是 low < high;

2. mid=(low+high)/2 容易导致数据溢出(Integer占4个字节,虽然通常数据集合中没那么多数据),所以这里写成 min = low + ((high - low) >> 1);

3. low 和 high 的更新,不能写成 low = min 、 high = min。可能会造成 low = high,导致一直循环。

二分查找的变种

  • 查找第一个等于给定值的数据
  • 查找最后一个值等于给定值的元素
  • 查找第一个大于等于给定值的元素
  • 查找最后一个小于等于给定值的元素

1. 查找第一个等于给定值的数据

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

2. 查找最后一个值等于给定值的元素

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

3. 查找第一个大于等于给定值的元素

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

4. 查找最后一个小于等于给定值的元素

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

扩展: letcode 33 题

 

static int text(int[] a, int value) {
	if (a == null || a.length == 0) {
		return -1;
	}
	int low = 0;
	int high = a.length - 1;
	while (low <= high) {
		int min = low + ((high - low) >> 1);
		if (a[min] == value) {
			return min;
		}
		if (a[low] <= a[min]) {
			// min 前半部分是有序数组,后半部分是有序循环数组
			if (a[low] <= value && a[min] > value) {
				high = min - 1;
			} else {
				low = min + 1;
			}
		} else {
			// min 后半部分是有序数组,前半部分是有序循环数组
			if (a[min] < value && a[high] >= value) {
				low = min + 1;
			} else {
				high = min - 1;
			}
		}
	}
	return -1;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值