【leetcode】几种二分法的标准书写格式

记这篇笔记的原因是我对二分法书写缺少一种标准和思维模式。
二分法理解起来虽然简单,但是在书写的时候有很多细节需要注意,比如二分的起始终止条件是什么(while(i!=j) while(i<j) while(i<=j))?二分范围的缩进要如何实现(是头尾同时缩进还是只缩进一端)?
这些细节上的问题要慢慢处理的话很麻烦,我希望积累一些标准的二分法的书写格式,这样在限定时间内完成题目的时候可以更方便一点。

场景一

实现一个简单的二分查找:对于升序数组,判断目标数target是否在数组中。

例如对于数组nums[1,4,5,7,8],8在数组中,而6不在数组中。

代码实现:
public boolean binarySearch(int[] nums,int target) {
	int mid,i=0,j=nums.length;
	while(i<=j) {
		mid=(i+j)/2;
		if(target==nums[mid])	return true;
		else if(target>nums[mid])	i=mid+1;
		else j=mid-1;
	}
	return false;
}

一些结果示例:

代码说明

首先我们需要在数组中找到的是刚好等于目标数的数字,这里就提示了二分范围i和j缩进的形式:
当target>nums[mid]时:i=mid+1
当target<nums[mid]时:j=mid-1

同时二分查找循环的条件是while(i<=j) 而不是while(i<j)。因为如果目标数如果刚好是在边界(即目标数 == nums[i]或者目标数 ==nums[j])那最终会搜索到i==j的时候才会找到目标数。
如果不检查最后一遍i==j的情况,二分查找就会失败。




场景二

有一个数组,要求当给一个目标数时,让目标数替换数组中刚好大于等于它的那个数。

例如对于nums[1, 3, 6]和target=2,由于3刚好是大于等于2的那个数,替换之后数组变为[1,2,6].
再例如对于数组nums[1,3,6,8,9,13,22],给定目标数为7后,可以替换掉数组中的8,数组变为[1,3,6,7,9,13,22]

代码实现:
public void binarySearch(int[] nums,int target) {
	int mid,i=0,j=nums.length-1;
	while(i!=j) {
		mid=(i+j)/2;
		if(target>nums[mid])
			i=mid+1;
		else
			j=mid;
	}
	nums[i]=target;
}

一些结果示例:

代码说明

首先我们需要在数组中替换的是大于等于目标数的数字,所以这里就提供了二分范围起点i和终点j的缩进形式为:
当target>nums[mid]时:我们要替换的数不可能是nums[mid],因为我们需要替换的数是大于等于target的数,而nums[mid]<targer。所以缩进方式为i=mid+1
当target<nums[mid]时缩进方式为j=mid而不是。因为nums[mid]有可能刚好就是我们需要替换的那个数,所以不能是j=mid-1,因为这样可能会跳过我们要找的数。

这个场景的应用在leetcode第300题上:
问题:https://leetcode.com/problems/longest-increasing-subsequence/submissions/
解法:https://segmentfault.com/a/1190000003819886

猜你喜欢

转载自blog.csdn.net/AXIMI/article/details/90647076