关于二分查找,该怎么判断条件?

有没有人能给一下二分查找的常见的问题和技巧什么的汇总啊?
本题:https://www.luogu.com.cn/problem/P1020

对于第一个求最长不上升子序列,本人一开始的二分查找是这样的:


```c++
    for (int i=1;i<=n;i++){
        if (st[top]>=a[i]) st[++top]=a[i];
        else{
            int l=1,r=top;
            while (l<r){
                mid=(l+r)>>1;
                if(st[mid]>a[i]) l=mid+1;
                else r=mid; 
            } 
            st[l]=a[i];
        }


结果错了但是把>改成>=就行了,如下:

    for (int i=1;i<=n;i++){
        if (st[top]>=a[i]) st[++top]=a[i];
        else{
            int l=1,r=top;
            while (l<r){
                mid=(l+r)>>1;
                if(st[mid]>=a[i]) l=mid+1;
                else r=mid; 
            } 
            st[l]=a[i];
        }
    }


```c++

这是怎么回事?以及遇到题该如何判断类似的情况?

答案来自GPT:
原始代码中的判断条件是if(st[mid]>a[i]),当遇到相等的情况时,应该将l=mid+1,而不是l=mid。因为如果相等时将l=mid,会导致在后续的判断中,lr的值不再发生变化,从而导致死循环。所以将判断条件改为if(st[mid]>=a[i])可以解决这个问题,确保算法的正确性。
===============================================================================================================1. 数组必须是有序的:二分查找只能在有序数组中进行查找,如果数组无序,则需要先进行排序操作。

  1. 边界条件的处理:在实现二分查找时,需要特别注意边界条件的处理。比如,当数组为空时,或者目标值小于数组的最小值或大于数组的最大值时,应该返回特定的结果。

  2. 循环终止条件的选择:在实现二分查找时,需要选择合适的循环终止条件。常见的选择有两种:一种是low <= high,另一种是low < high。选择哪种条件取决于具体的问题需求。

  3. 中间值的计算:在每一轮循环中,需要计算中间值。常见的计算方法是mid = (low + high) / 2。需要注意的是,如果数组的长度很大,可能会导致整数溢出问题,可以使用mid = low + (high - low) / 2来避免。

  4. 目标值的判断:在每一轮循环中,需要判断目标值与中间值的关系,以确定下一轮查找的范围。常见的判断方法有三种:目标值等于中间值、目标值小于中间值、目标值大于中间值。根据具体问题需求选择合适的判断方法。

  5. 边界值的处理:在确定下一轮查找的范围时,需要特别注意边界值的处理。比如,当目标值小于中间值时,应该将high更新为mid - 1;当目标值大于中间值时,应该将low更新为mid + 1

二分查找只能用于已经排序完成的数组。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7639716
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:【数据结构与算法】粽子树?二叉树_关于堆你不知道的事情
  • 以下回答来自chatgpt:

    根据问题描述,你遇到了一个关于二分查找的问题,具体来说是在解决这个题目中的第一个问题,求最长不上升子序列时尝试使用二分查找但遇到了问题。

    首先,让我们来看一下问题的代码示例:

    // 在这里展示你的代码示例或描述你的具体尝试
    

    很抱歉,你没有提供你的具体代码实现,这样我无法分析你的问题所在。下面,我会列举一些关于二分查找的常见问题和技巧,希望对你有所帮助。

    关于二分查找的常见问题和技巧:

    1. 确定搜索区间:二分查找通常会在一个有序的序列中进行搜索,首先需要确定搜索的区间。最常见的做法是使用两个指针 leftright 分别指向序列的起始和结束位置。

    2. 计算中间位置:通过求取 mid 的方式来计算中间位置,例如 mid = (left + right) // 2

    3. 判断终止条件:一般情况下,终止条件是 left > rightleft >= right,这表示整个序列已经遍历完毕或搜索区间为空。

    4. 更新搜索区间:根据需要更新搜索区间,通常是根据当前中间位置的值与目标值的大小关系,如果目标值比中间位置的值小,则更新 right = mid - 1,如果目标值比中间位置的值大,则更新 left = mid + 1

    5. 判断条件与边界:在使用二分查找时,需要正确判断条件与边界。具体而言,需要考虑以下几个方面:

      • 判断目标值是否存在:在更新搜索区间后,需要判断目标值是否与中间位置的值相等,如果相等,则表示已经找到目标值。
      • 判断搜索区间是否合法:每次更新搜索区间后,需要判断当前的搜索区间是否合法,即 left <= right
      • 是否需要加入等号:在比较目标值与中间位置的值时,需要根据具体情况决定是否需要加入等号。
      • 边界条件的选择:在更新搜索区间时,需要根据具体问题选择合适的边界条件。

    根据你的问题描述,你遇到了一个二分查找的问题,并希望得到一些关于二分查找的指导。很抱歉,由于你没有提供具体的代码示例,我无法分析你代码中可能存在的问题。但我希望以上关于二分查找的常见问题和技巧对你有所帮助。如果你能提供具体的代码示例,我将会更具体地指导你解决问题。如果你有其他关于二分查找的问题,也欢迎继续向我提问。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^