二分查找的学习与应用


前言

在生活中,我们如果单单只是将书整理到书架上,那么我们找到一本书是比较困难的,因为我们需要一个个遍历书架上的书,但是如果我们将书按照拼音排序,那么对于我们寻找书是有帮助的,这就涉及到了我们二分查找的中一个基本思想----有序。


`

一、二分查找的定义

二分查找(Binary search)也称折半查找,是一种效率较高的查找方法。但是,二分查找要求线性表中的记录必须按关键码有序,并且必须采用顺序存储。

二、二分查找的基本思想

有序表中,取中间记录作为比较对象。 若给定值与中间记录的关键字相等,则查找成功
若给定值小于中间记录的关键字,则在中间记录的左半区继续查找
若给定值大于中间记录的关键字,则在中间记录的右半区继续查找 不断重复上述步骤直至查找成功

三、二分查找的方法

笔者通过粗略地学习二分算法,了解到二分算法分为两种方法,一种是左闭右闭,一种是左闭右开
这两种方法实现的功能是相同的,但是背后的逻辑却略有不同。

四、二分查找的细节

细节1

首先我们要明白:
用于查找的内容一定是有序的。也就是说,我们所需要查找的数组已经是排好顺序的
另外我们还需知道我们使用二分查找时仅仅只能查找一个元素。

在二分查找中,目标元素的查找区间是很重要的,不同的区间定义的写法是不一样的

左闭右闭 [left, right]
左闭右开 [left, right)
因为实现的功能相同,这里我着重介绍我认为更容易理解的左闭右闭的方法

细节2

重点:
且我们不需要纠结二分查找的数组中的元素是奇数个还是偶数个,

但是千万不要一直纠结中间的数字两边的数字数量不一样这个问题,因为:

两边数量不一样是一定会出现的情况
但是这种情况并不影响我们对中间数字和目标数字大小关系的判断

只要中间数字大于目标数字,就排除右边的
只要中间数字小于目标数字,就排除左边的

五、二分查找的优点

二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.
时间复杂度即是while循环的次数。
总共有n个元素,
渐渐跟下去就是n,n/2,n/4,…n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示O(h)=O(log2n)

六、二分查找的码实现

# include <stdio.h>
# include <malloc.h>
int binary_search(int* a, int key, int len)
{
	int left = 0;
	int right = len - 1;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (key < a[mid])
		{
			right = mid - 1;//中间值大于key则查找左半区
		}
		else if (key > a[mid])
		{
			left = mid + 1;//中间值小于key则查找右半区
		}
		else
			return mid;
	}
	return 0;
}

int main()
{
	int n;
	printf("请输入数组长度");
	scanf_s("%d", &n);
	int* a = (int*)malloc(sizeof(int) * n);
	for (int i = 0; i < n; ++i)
	{
		scanf_s("%d", &a[i]);
	}
	printf("请输入要查找的数字");
	int num;
	scanf_s("%d", &num);
	printf("%d", binary_search(a, num, n));

	return 0;
}

七、二分查找的例题

例题:
搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5 输出: 2 示例 2:

输入: nums = [1,3,5,6], target = 2 输出: 1 示例 3:

输入: nums = [1,3,5,6], target = 7 输出: 4

提示:

1 <= nums.length <= 104
-104 <= nums[i] <= 104 nums 为 无重复元素 的 升序 排列数组
-104 <= target <= 104

int searchInsert(int* nums, int numsSize, int target){
    int left = 0;
    int right = numsSize-1;
    while(left<=right)
    {
        int mid = (left+right)/2;
        if(target==nums[mid])
        {
            return mid;
        }
        if(target<nums[mid])
        {
            right = mid-1;
        }
        else if(target>nums[mid])
        {
            left = mid+1;
        }
       
    } return left;
    //纯二分搜索[704]是返回return -1,这里要按顺序插入,所以返回left索引位置
}

总结

笔者仅仅对二分查找进行了粗略的学习,但对其中的逻辑并不能完全理解,将会在下周开始刷题强化自己的理解

本文仅用于记录笔者自己学习与进化的过程,如有错误,请不吝指出

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值