代码随想录 day1

二分法的使用

对于二分法,我们首先要明确一点,就是right究竟取何值。

right = nums.length - 1 or right = nums.length ?

其实这这两种都是二分法的形式,只不过看你如何区分区间。

case1:

left = 0 , right = nums.length

整体的模板形式如下:

        while (left < right){

                int mid = left + ((right - left)>>1);

                if (nums[mid] < target){

                        left = mid + 1;

                } else if (nums[mid] > target){

                         right = mid - 1;

                }else{

                        return mid;

                }

        }

我们注意到几个关键点,while的条件是left < right ,为什么不是left <= right呢? 还记得right的初始值是nums.length吗,这个值本身不包含在nums可以取到的下标里,也就是说这其实是应该左闭右开的区间,开区间的值取不到就谈不来讨论等于了。

同时对于 left = mid + 1, 与 right = mid - 1,为什么要这样写,很简单,对于小于target的情况此时的mid已经是小于了,之后讨论的值无需带上它。对于大于target,由于right是开区间,在下一次进入循环时讨论右区间的值是没有意义的,只有mid - 1才有意义。

case 2:

left = 0 , right = nums.length - 1

整体的模板形式如下:

        while (left <= right){

                int mid = left + ((right - left)>>1);

                if (nums[mid] < target){

                        left = mid + 1;

                } else if (nums[mid] > target){

                         right = mid;

                }else{

                        return mid;

                }

        }

此时 while的条件就变为了 left <= right , 显而易见的原因是right此时的值是一个可以取到的值,是左闭右闭的区间,当小于target的时候,由于同样的原因,left = mid + 1,而right此时由于可以取到的,所以保持mid即可。

例题1:

简单的二分用法,无需解释

例题2:

上一题的变体,若值不存在,由于是一个顺序数组,nums【mid】最后一定是小于target的,此时left = mid + 1,也就是left++,此时left来到了应该被插入的位置。

例题3:

对于此题,我的思路就是先找出一个值,从这个值往两边扩,直到扩不动。

例题4:

此题,可以直接return两个特殊值,由平方的性质可知,结果一定是在小于x的一半的区间中产生。注意,在判断时 采用 mid * mid <= x 会产生溢出,所以使用除法. 在mid <= (x/mid)的区间内,可能会有值也可能没有值(取等时为答案),我们每一次都将该值赋给结果,二分到最后,只会留下相等的值,即为结果。

例题5:

本题是例题4的变体,由平方的性质可知right取num的一半, 其余直接二分即可

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值