二分思想有感

目录

文章目录

前言

一、二分模板

模板1(闭区间)

模板2(左闭右开)

模板3(开区间)

二,二分思想

1,引入

2,具体分析

3,总结

结语



前言

本篇文章将介绍二分法的思路及例题


一、二分模板

废话少说,献上模板

模板1(闭区间)

//一
int search(int* nums, int numsSize, int target) {
	int left = 0;int right = numsSize - 1;
	while (left <= right) {
		int mid = left + (right - left) / 2;
		
//条件判断
		if (nums[mid] == target) { return mid; }
		else if (nums[mid] < target) { left = mid + 1; }
		else { right = mid - 1; }


	}

	return -1;//找不到返回-1
}
//------------------------------------------
//二
int search(int* nums, int numsSize, int target) {
	int left = 0;int right = numsSize - 1;
	while (left <= right) {
		int mid = left + (right - left) / 2;

		//条件判断
		
		 if (nums[mid] < target) { left = mid + 1; }
		else { right = mid - 1; }


	}
	if (left<numsSize&&nums[left] == target) { return left; }
	return -1;
	
}

模板2(左闭右开)

int search(int* nums, int numsSize, int target) 
{int left = 0, right = numsSize-1;
	while (left < right) {
	
	int mid = left + (right - left) / 2;
	
	 if (nums[mid] < target) { left = mid + 1; }
	else { right = mid; }
}

	if (left < numsSize && nums[left] == target) { return left; }
	return -1;

}

模板3(开区间)

int search(int* nums, int numsSize, int target) 
{
	int left = 0, right = numsSize - 1;
while (left + 1 < right) {
	
	int mid = left + (right - left) / 2;
	
 if (nums[mid] < target) {
		left = mid;
	}
	else {
		right = mid;
	}
}

if (right >=0 && nums[right] == target) { return right; }
return -1;


}

二,二分思想

1,引入

用来引入中心思想及用图理解

在解释各个模板之前,本人想法来自灵神及其评论区的讨论(视频链接在下方)https://www.bilibili.com/video/BV1AP41137w7/?vd_source=430c819dcfec0ed4686f19278a5b1e20中心思想:区间内的性质不重要,记住区间外的性质 

模板1:闭区间,本人更习惯使用第二种(模板1),就用第二种为例讲(讲法是默认递增数组,从while条件入手,逐步推出while内left和right的更新条件)

模板1,while的结束条件是right在left右边,若我们认为最后是left在 target 的位置,那么有下图的关系

再解释上图中覆盖区域的意思:right一开始在数组最右边,移动方向自然只能向左移,那么导致right每次移动的条件就同样对覆盖区域有用

(举例:

if(nums[right]>1){right--;}

那么right走过的地方都满足nums[right]>1

这就是上面指向思想的本质:关注区间之外


2,具体分析

使用 “引入” 来分析并得出left和right的更新条件

回到本来的问题,target正好在两个区域交界,再结合二分的思想中mid(减半再分析)

如果mid对应的值大于target,那就更新right---------问题是怎么更新:

mid已经大了,那么就不要,让right=mid-1;

同理:mid<target-------left=mid+1;

mid==target--------return mid;

按上面的想法似乎可行,但这不是我一开始想要的模板1的第二种,

再结合上文的中心思想,

让if(left>mid),left=mid-1;

if(right<=mid),mid=right-1;

结合上面的图和中心思想:left左边是小于mid,right右边是大于等于mid


3,总结

模板1的染色法分析

再用该思路分析其他模板

模板2:从while的终止条件得出最后left=right;若left左边都小于target,我们要得到答案,就要right的右边及本身要大于等于target

从上面两个模板的不同,可以分析出:

由于while的终止条件不同,对left及right的更新条件也会不同,要根据终止条件及区间外重要的思想去构造更新条件

模板3也同理

所以最后return right


结语

“自己试试看吧”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值