来玩二分查找[NO.1]

来玩二分查找

二分查找是典型的看起来很普通,当时细节却很复杂的算法,可以理解为:思路很简单,细节是魔鬼,各种边界情况复杂,如果想不通不妨在纸上模拟计算。

本篇博客就开始来探寻一下二分查找,常用的几个二分查找,寻找一个数,寻找左侧边界,寻找右侧边界等情况,循环结束条件是什么,索引到底是该加一还是减一等情况,分析细节及细节的差异。

先来一个简单的二分查找代码

public static void getTwoNum4(int[] arr, int num) {
		int left = 0;
		// 数组索引从0开始,长度从1开始
		int right = arr.length - 1;

		// 为什么要小于等于,必须以left或right为标的,大于覆盖一边,否则如果是相等,则相等的索引就会被漏掉
		// 这里可以带入(3<=2) 只有当left+1>right循环终止,且区间为空
		while (left <= right) {
			int index = (left + right) / 2;
			if (num == arr[index]) {
				System.out.println("找到符合要求的数:" + arr[index]);
				break;
			} else if (arr[index] > num) {
				// 传统做法right--相当于从右向左完整遍历,当索引值大于目标数,则右侧索引减一
				// right--;
				// 根据索引值大于目标数,从索引处减一,排除索引右侧大于目标数,复杂度更小
				right = index - 1;
			} else if (arr[index] < num) {
				// 传统做法left++相当于从左向右完整遍历,当索引值小于目标数,则左侧索引加一
				// left++;
				// 根据索引值小于目标数,从索引处加一,排除索引左侧小于目标数,复杂度更小
				left = index + 1;
			}
		}
	}

细节问题

  • right索引为什么是 arr.length-1?
    答:数组索引下标从0开始,数组的长度从1开始,右侧数组最大索引是长度-1,否则会越界

  • 为什么while的循环条件是<=而不是<

在这里插入图片描述
从图上可以看出来,必须以left或right为标的,大于覆盖一边,否则如果是相等,则相等的索引就会被漏掉,如上图第一列数组,如果循环条件是while(left<rigth)带入(3,3),循环结束则会漏掉索引3,如上图第二列数组,如果循环条件是while(left<=rigth)带入(3,2),没有数字比3大比2小,则while循环完整结束。

  • 循环判断条件arr[index]>num为什么right=arr[index]-1
    答:传统做法是当索引值大于目标值,右侧索引减减,相当于从右向左完整遍历查找,二分查找是当(left+right)/2,获取数组中间索引值,比较如果大于目标数值,则代表目标数值在于数组的左侧,排除索引右侧大于目标数,所以right索引为index-1;同理如果数组中间索引值,比较小于目标数值,则代表目标数值在于数组右侧,排除索引左侧小于目标数,所以left的索引为index+1,查找复杂度更小。

左侧边界和右侧边界二分查找后续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值