算法讲解一之二分查找法

算法学习篇一:二分查找法

声明

本文旨在记录自己学习算法期间对相关知识的理解与运用,因为博主也是学习者,如有与其他文章相同的地方,还望理解。

引言

我想大家对二分查找并不陌生,二分查找主要用于查找元素中的数组的位置,但从算法角度看,我们通过分析二分查找的过程,找到了数组中某个元素的位置。
但是我们应在理解算法的基础上,将二分查找算法应用具体的项目过程中去,这样,我们才真正的不止于学习,而且在不断的实践,这对能力的提升是很有帮助的。

二分查找详解

以一个具体的示例来看(经典力扣题
题目: 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

输入: nums = [-1,0,3,5,9,12], target = 9     
输出: 4  

思路

解法一:数组指针,循环比较

  1. 得到数组的长度,作为循环的次数
  2. 定义一个指针指向数组首地址
  3. 从数组0地址开始,在循环中判断目标值与指针指向的数组元素是否相等,同时设一个变量,如果相等,用来记录当前元素的下标;否则,指针+1,直到循环结束。
  4. 返回下标值或者-1。

解法二:二分查找法

  1. 确定二分查找法的对象是有序数组,并且没有重复的元素,这两点很重要。
  2. 根据区间定义的不同,二分查找法分两种:左闭右闭[left,right];左闭右开[left,right)。
    (至于为啥没有其他的,比如左开等,原因就像你爬山,却没有山是一个道理)。
  3. 代码如下(C++,C):
    C++编写函数
    法一:左闭右闭[left,right];
class makeup{
publicint index_search(vector<int>& nums,int target)
{
	int left=0;//用来表示数组的起始下标
	int right=nums.size()-1;
	int middle=left+(right-left)/2;//等同于middle=(left+middle)/2;
	while(left<=right)//之所以是<=,是因为[left,right]区间都闭,即当left=right=a;middle=a;有效
	 {
	if(nums[middle]>target)//如果目标值小于数组的中值,则在左边
	  {
	  right=middle-1;//右边界应该为middle-1
	  }
	else if(nums[middle]<target)如果目标值大于数组的中值,则在右边,因为是有序数组
		{
		left=middle+1;//左边界应该为middle+1;
		}
	else
	{
	return middle;//如果相等,返回下标
	}
	return -1;//未找到返回-1
	 }//结束判断
	}
};

法二:左闭右开[left,right);

class makeup{
publicint index_search(vector<int>& nums,int target)
{
	int left=0;//用来表示数组的起始下标
	int right=nums.size();
	int middle=left+(right-left)/2;//等同于middle=(left+middle)/2;
	while(left<right)//之所以是<,是因为[left,right),即当left=right=a;middle=a;无效
	 {
	if(nums[middle]>target)//如果目标值小于数组的中值,则在左边
	  {
	  right=middle;//右边界应该为middle
	  }
	else if(nums[middle]<target)如果目标值大于数组的中值,则在右边,因为是有序数组
		{
		left=middle+1;//左边界应该为middle+1;
		}
	else
	{
	return middle;//如果相等,返回下标
	}
	return -1;//未找到返回-1
	 }//结束判断
	}
};

C编写函数,思想与法一 一样。

int index_search(int* nums,int numsize,int target)
{
int left=0;
int right=numsize-1;
int middle=left+(right-left)>>1;
while(left<=right)//之所以是<=,是因为[left,right]区间都闭,即当left=right=a;middle=a;有效
	 {
	if(nums[middle]>target)//如果目标值小于数组的中值,则在左边
	  {
	  right=middle-1;//右边界应该为middle-1
	  }
	else if(nums[middle]<target)如果目标值大于数组的中值,则在右边,因为是有序数组
		{
		left=middle+1;//左边界应该为middle+1;
		}
	else
	{
	return middle;//如果相等,返回下标
	}
	return -1;//未找到返回-1
	 }//结束判断
}

总结

其实问题的关键还是数组首地址是从0开始的,即一个10元素的一维数组,下标范围[0,9],一共10个数;下标范围最大是9,但元素数有10个,法一从下标的角度出发,法二从元素数的角度出发的。

附加知识点:

vector与array:

1. ector数组是一个能存放任意数据类型(类,结构,普通变量类型等)的动态数组
2. 和普通数组一样可以通过下标索引来进行访问

具体的可以去网上找一下说明,附链接vector、Array及数组区别

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值