前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ChatGPT,为啥写二分搜索容易死循环?

ChatGPT,为啥写二分搜索容易死循环?

原创
作者头像
Mark Sun
修改2023-03-30 23:38:02
5820
修改2023-03-30 23:38:02
举报

背景

这段时间ChatGPT在码农界,引起了不小轰动,最热的话题中有一个与程序员息息相关,它会写代码那程序员是不是会集体下岗? 刚好最近听说了这么一句话,“90%程序员都写不对二分搜索”,那就整个二分搜索最常见的问题考考ChatGPT


了不起: 为什么写二分搜索容易死循环?

ChatGPT: 一个常见的原因是在二分搜索中没有正确处理边界情况,例如:

1、非递归实现中,循环终止条件可能不正确,导致死循环;

2、递归实现中,递归条件可能不正确,导致无限递归。

此外,当待搜索的数组不是有序时,也可能导致搜索结果不正确或死循环。 如果你遇到了这个问题,可以仔细检查你的代码并尝试调试。可以使用打印语句或者调试器来寻找问题所在。同时,你也可以参考其他人的代码或者算法实现,再次检查你的思路是否正确。


了不起觉得,还算是一个中规中矩的答案,并没有十分惊艳,不过也讲到了关键所在就是条件处理。

随后让它给出一个二分搜索的代码,也与搜索引擎提供基本一致,没有系统的对二分问题做出分类,以下了不起总结的普通二分和不等式二分,几乎涵盖了所有的二分问题的方法论。

一、普通二分搜索

普通的二分搜索,就不再赘述,属于基本功了,现在的大多数算法面试也基本不再问。

1.1 编码实战
代码语言:javascript
复制
public class _1_BinarySearch {
    public int basicBinarySearch(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
}
1.2 注意点

实数的二分就不用考虑所谓的mid+1和mid-1,因为index是整数是离散的,不是连续精确的,变更区间条件时出现死循环。

二、不等式二分搜索

2.1 三步走

1、写出二分的条件,需要满足的条件,包含mid的branch;

2、条件放到if,确定要求满足条件的mid的min(right = mid)或者max(left = mid);

3、else left = mid + 1 或 right = mid - 1,后者需要在mid取值的时候补上+1。

2.2 注意点

mid取值补上1,是为了防止死循环,当left和right为5和6时,模拟想想。

前驱和后继和条件本身无关,与是否满足条件相关,如果是满足求min即是后继。

需要考虑如何表示无解?前驱left = -1,表示无解;后继right= n,表示无解。

2.3 编码实战

一段有序的数组但是有重复数组,搜索出目标数字的index区间。

代码语言:javascript
复制
public class _1_BinarySearch {
    public int[] searchRange(int[] nums, int target) {
        int leftBound = leftBound(nums, target);
        int rightBound = rightBound(nums, target);
        if (leftBound > rightBound) {
            return new int[]{-1, -1};
        }
        return new int[]{leftBound, rightBound};
    }
    // 前驱型往前找
    int rightBound(int[] nums, int target) {
        int left = -1;
        int right = nums.length - 1;
        while (left < right) {
            int mid = (left + right + 1) / 2;
            if (nums[mid] <= target) {
                left = mid; // max 向右扩张
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
    // 后继型往后找
    int leftBound(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        while (left < right) {
            int mid = (left + right) / 2;
            // 条件考虑了nums[mid],即func(mid)的递增递减关系,需要满足这个条件
            if (nums[mid] >= target) {
                right = mid; // min 向左收缩
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

小结

1、以上二分搜索,对于mid是否溢出均未处理,如果给了数据集接近int的max,那么可以这么取mid = left + (right - left) / 2。

2、不等式二分搜索,属于常考的题目了,用于求取一些难解问题的最优值,这些难解的问题都有一个特点,问题可以转化成判定问题,这时候就可以二分的条件求值。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、普通二分搜索
    • 1.1 编码实战
      • 1.2 注意点
      • 二、不等式二分搜索
        • 2.1 三步走
          • 2.2 注意点
            • 2.3 编码实战
            • 小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档