【LeetCode】·【704. 二分查找】·【不成功】

记一次失败的二分法查找

class Solution {
    public int search(int[] nums, int target) {
         if(nums.length == 0){
             return -1;
         }
         if(nums.length == 1){
             return nums[0]==target? 0:-1;
         }
         int half =  (nums.length - 1) / 2;
         int oldhalf = 0;
        while(true){
           if(nums[half] == target){
               return half;
           }else if(nums[half] > target){
               int newHalf =half - ((half-oldhalf) /2);
               if(newHalf == (half-1)){
                   if(nums[newHalf] != target){
                       return -1;
                   }else{
                       return newHalf;
                   }
               }
               half = newHalf;
           }else{
               int newHalf = (nums.length-half)/2+half;
               if(newHalf == half+1){
                   if(nums[newHalf] != target){
                       return -1;
                   }else{
                        return newHalf;
                   } 
               }
               oldhalf = half;
               half = newHalf;

           }
        }
    }
}

一开始的解题思路是这样的

我想用长度除以2的方式,获取中间的下标,之后用中间的下标获取值对比。如果值等于 直接返回下标,如果值大于,则下标除2,如果值小于,则搞一个下标在后面一半数组的中间。

一开始还有另一种解题思路,我每次都新建一个数组,数组是之前数组二分后的结果。但是考虑到要弄一堆数组出来就放弃了。

于是开始实现,一开始的代码是这样的。

class Solution {
    public int search(int[] nums, int target) {
        
         int half =  (nums.length - 1) / 2;

        while(true){
           if(nums[half] == target){
               return half;
           }else if(nums[half] > target){
               int newHalf =half - ((half-oldhalf) /2);
               half = newHalf;
           }else{
               int newHalf = (nums.length-half)/2+half;
               half = newHalf;

           }
        }
    }
}

很快就遇到了问题,如果找的数字不存在,比如它是10,但是数组只有9,12。直接没法跑出循环

于是我觉得,如果不存在,就说明至少找到了他应该存在的区间的地方。也就是新的下标加一或减一还是不等于值的话,那就妥妥的不存在了。

于是我把代码加上了

if(newHalf == (half-1)){
                   if(nums[newHalf] != target){
                       return -1;
                   }else{
                       return newHalf;
                   }
               }
if(newHalf == half+1){
                   if(nums[newHalf] != target){
                       return -1;
                   }else{
                        return newHalf;
                   } 
               }

这样是跑出循环了,只要一直找下去就能找的到。但是不行,因为不是一直找下去的。如果二分的时候,新的下标值不是目标值,下标和旧下标又不差1,也就是说如果他二分发现,太小了,我得回去,那我这时候根本就没有二分,而是此时到之前的所有元素二分。

也就是第一次 1到5,5到10

第二次 发现,要到5到10里面找,发现7太大,于是得回去,结果回去找是在1到7里面找。

这里就感受到了,我需要不新建数组,却要达到记录二分的范围,而且还得让每次计算后的结果,都是二分,缩小查询范围。

我想到能不能让代码知道我之前发现太大的下标,之后再用这个下标和新的下标来获取需要查询的范围。

于是就变成开篇那样。

我在向后寻找的代码里,添加了记录当时下标的值。

测试通过了。

但是出现了极端情况。

[2,5]这样的两个元素数组,一开始就到头了,除来除去跳不出循环。直接超时。

我放弃了,看了答案。 答案用左右两个下标,来缩短范围,也就是先二分,如果值小于,就把范围缩到这个下标,大于就把范围缩到这个下标。

对比我切一半,看一半,一半不对再切的方法,我这种方法就是认定了要么一直向左,要么一直向右。

而两个下标的方法一开始就考虑到要对中间聚拢,而且不考虑聚拢后不在范围的。

【leetcode的答案】

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            int num = nums[mid];
            if (num == target) {
                return mid;
            } else if (num > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/binary-search/solution/er-fen-cha-zhao-by-leetcode-solution-f0xw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值