我是真的不会写二分呀——二分查找详解!!!

本文详细介绍了二分查找算法,包括它的概念、算法思想、步骤、实现方式(非递归和递归)以及在实际编写代码时可能会遇到的问题,如中间元素的定位、while循环条件的选择和边界处理。通过阅读,读者可以深入理解二分查找并避免常见的编程陷阱。
摘要由CSDN通过智能技术生成

  二分查找算法我们会经常对它进行应用以及拓展,但它看起来很简单,实则漏洞状况百出,编写二分查找的算法就很迷惑,云里雾里,不要着急,看完这篇,立马干掉这个难题。
在这里插入图片描述

二分查找

1.概念
二分查找是查找算法的一种,它又被称为折半查找,适用于有序数组中的查找。我们在平常进行查找时最通用的方法就是:对数组进行遍历,依次比较每个元素(即顺序查找)。二分查找对其进行优化,将每次的比较查找范围缩小了一半。

2.算法思想
二分查找就是将查找的的元素和子数组的中间值进行比较,如果查找元素小于中间值,就在左子数组中继续查找;如果查找元素大于中间值,就在右子数组中继续查找,否则中间值就是要找的元素。

3.算法步骤

  • 首先找到数组查找区间的中间位置mid=(left+right)>>1;

  • 用待查找元素值与中间位置值进行比较;
    若=,则查找成功;
    若<,则在 左子数组中继续进行查找;
    若>,则在 右子数组中继续进行查找;

  • 查找成功,返回元素所在的数组下标;

4.算法的实现

  • 非递归(常用)
//非递归算法
int binarySearch(int[] arr, int target)
{
	int left = 0;
	int right = arr.length - 1;

	while (left <= right)
	{
		int mid = (left + right) >> 1;
		if (target == arr[mid])
			return mid;
		else if (target < arr[mid])
			right = mid - 1;
		else if (target > arr[mid])
			left = mid + 1;
	}
	return -1;
}
  • 递归(较少应用)

(该数组为升序排列)

int binarySearch_ecursion(int arr[], int target, int left, int right)
{
	int mid = 0;
	if (left <= right)
	{
		mid = (left + right) >> 1;
		if (target == arr[mid])
			return mid;
		else if (target < arr[mid])
			return binarySearch_ecursion(arr, target, left, mid - 1);
		else if (target > arr[mid])
			return binarySearch_ecursion(arr, target, mid + 1, right);
	}
	return -1;
}

5.复杂度分析

  • 时间复杂度:O(log2n)

代码编写时的坑

1.定位中间元素
定位中间元素时需要考虑防止溢出的情况,直接将left和right相加数字太大时会导致溢出,mid=(left+right)>>1left+(right- left)/2都可以有效的防止溢出。

2.while循环的条件——(<=)和(<)的选择
首先我们在初始化时right=arr.length - 1,即是最后一个元素的下标;
其次,什么时候该停止搜索呢,当然是找到目标值的时候停止,如果没有找到,就需要while循环进行终止,然后返回-1;
<=和<两者可能出现在不同功能的二分查找中,<=相当于[left, right],<相当于[left, right),这样就会导致索引大小出现越界的情况。
解释:

  • while(left<right),的终止条件是[left,right),如果我们待查找的元素为2,遇到[2,2),这个时候循环进行终止,而我们的索引2也没有被搜索到直接返回了-1,这样就导致了我们查找出错(漏掉元素)。

3.为什么left=mid+1,right=mid-1,怎样判断对其进行加减呢?
这里也是算法中一个难点,但是我们上面分析了搜索区间为[left, right],当索引值和我们元素值不匹配时,下一步如何进行查找呢?

  • [left,mid-1],查找元素小于中间值,就在左子数组中继续查找;
  • [mid+1,right],查找元素大于中间值,就在右子数组中继续查找;
  • mid已经搜索过,所以从区间中剔除;
  • 其对应代码就为如下:
  •  if (target == arr[mid])
     	return mid;
     else if (target < arr[mid])
     	right = mid - 1;
     else if (target > arr[mid])
     	left = mid + 1;
    

这里附上之前在力扣看到某位大佬总结的一首二分要点小诗: 在这里插入图片描述
如上,大家是否对二分有了更深刻的认识与了解呢?再也不会因为边界问题而苦恼啦~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值