当前位置: 首页 > 知识库问答 >
问题:

在排序数组中查找比给定值最低和最大的元素的二分搜索?

澹台啸
2023-03-14

因此,我试图实现二分搜索算法(尽可能通用,以适应不同的情况)。我在网上搜索了一下,有的使用while(low!=high),有的使用while(low!=high)等不同的条件,很让人困惑。

因此,我开始编写代码,查找第一个大于给定元素的元素。我想知道有没有比这更优雅的解决方案?

代码

#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>
#include <stack>
#include <queue>
#include <climits>
#include <set>
#include <cstring>

using namespace std;
int arr1[2000];
int n;
int main (void)
{
    int val1,val2;
    cin>>n;
    for (int i = 0; i < n; i++)
        cin>>arr1[i];
    sort(arr1,arr1+n); 
    cout<<"Enter the value for which next greater element than this value is to be found";   
    cin>>val1;
    cout<<"Enter the value for which the first element smaller than this value is to be found";
    cin>>val2;

    int ans1 = binarysearch1(val1);
    int ans2 = binarysearch2(val2);

    cout<<ans1<<"\n"<<ans2<<"\n";
    return 0;
}
int binarysearch1(int val)
{
    while (start <= end)
    {
        int mid = start + (end-start)/2;
        if (arr[mid] <= val && arr[mid+1] > val)
            return mid+1;
        else if (arr[mid] > val)
            end = mid-1;
        else
            start = mid+1;
    }
}

类似地,为了找到比给定元素小的第一个元素,

int binarysearch2(int val)
{

    while (start <= end)
    {
        int mid = start + (end-start)/2;
        if (arr[mid] >= val && arr[mid] < val)
            return mid+1;
        else if (arr[mid] > val)
            end = mid-1;
        else
            start = mid+1;
    }
}

当我不得不为这样的抽象修改二分搜索时,我经常会感到超级困惑。请让我知道是否有更简单的方法相同?谢谢!

共有1个答案

吕永嘉
2023-03-14

正如你所说的,有不同的方法来表达二分搜索的结束条件,它完全取决于你的两个极限的意思。让我来解释一下我的,我认为它很容易理解,而且它可以让你在其他情况下修改它,而不用考虑太多。

让我把这两个极限称为第一个和最后一个。我们想要找到第一个大于某个x的元素。以下不变量将始终成立:

在最后一个之前的每个元素都大于x,而在第一个之前的每个元素都小于或等于(相反的情况)。

注意,不变量并没有说明间隔[first,last]。不需要进一步了解向量的限制的唯一有效初始化是first=0和last=向量的最后位置。这就满足了这样一个条件,即在最后一个之后没有任何东西,在第一个之前没有任何东西,所以一切都是正确的。

由于区间[first,last]未知,我们将不得不继续直到它为空,从而更新极限。

int get_first_greater(const std::vector<int>& v, int x)
{
  int first = 0, last = int(v.size()) - 1;
  while (first <= last)
  {
    int mid = (first + last) / 2;
    if (v[mid] > x)
      last = mid - 1;
    else
      first = mid + 1;
  }
  return last + 1 == v.size() ? -1 : last + 1;
}

正如您所看到的,我们只需要两个案例,因此代码非常简单。在每一次检查中,我们都更新极限以始终保持我们的不变量为真。

当循环结束时,使用不变量,我们知道last+1大于x,如果它存在的话,所以我们只需要检查我们是否还在向量内。

记住这一点,您可以根据需要修改二进制搜索。让我们把它改成找到最后一个小于x的。我们改变不变量:

first之前的每个元素都小于x,last之后的每个元素都大于或等于x。

int get_last_smaller(const std::vector<int>& v, int x)
{
  int first = 0, last = int(v.size()) - 1;
  while (first <= last)
  {
    int mid = (first + last) / 2;
    if (v[mid] >= x)
      last = mid - 1;
    else
      first = mid + 1;
  }
  return first - 1 < 0 ? -1 : first - 1;
}
 类似资料:
  • 所以,我有一个所有正自然数的数组。给我一个阈值。我必须找出总和小于给定阈值的数字(连续的)的最大计数。 输入数组的最大大小可以为 10^5。 基本上,我想到了一种算法,它计算原始数组的子集中元素的数量,这些元素的总和将小于给定的阈值。但是,这将导致O(N^2).的复杂性有人能建议一个更好的算法吗?我不是在寻找一个代码,只有一个算法/伪代码将做得很好。谢谢!

  • 问题内容: 给你一个包含 1 到 n 的整数数组,但数组中从 1 到 n 的数字之一丢失了。您需要提供最佳解决方案来找到丢失的数字。数组中的数字不能重复。 例如: 问题答案: 用 初始化两个变量最大和最小 迭代数组 如果当前元素大于最大值,则将当前元素分配给最大值。 如果当前元素小于最小值,则将当前元素分配给最小值。 最后你会得到最小和最大的元素。 在数组中查找最小和最大元素的 Java 代码:

  • 本文向大家介绍在C ++中从给定的三个排序数组中查找三个最接近的元素,包括了在C ++中从给定的三个排序数组中查找三个最接近的元素的使用技巧和注意事项,需要的朋友参考一下 假设我们有三个排序的数组A,B和C,以及分别来自A,B和C的三个元素i,j和k,使得max(| A [i] – B [i] |,| B [j] – C [k] |,| C [k] – A [i] |)被最小化。因此,如果A =

  • 本节通过求数组的最大和最小值来提高初学者对数组的一些基本应用。 程序运行结果如下: 最高成绩:100 最低成绩:67 将变量 min 与 max 初值设成数组的第 1 个元素后,再逐一与数组中的各元素相比。比 min 小,就将该元索的值指定给 min 存放,使 min 的内容保持最小。同样,当该元素比 max 大时,就将该元素的值指定给 max 存放,使 max 的内容保持最大。for 循环执行完

  • 主要内容:普通算法,分治算法程序中,我们经常使用数组(列表)存储给定的线性序列(例如 {1,2,3,4}),那么如何查找数组(序列)中的最大值或者最小值呢? 查找数组(序列)中最大值或最小值的算法有很多,接下来我们以 {3,7,2,1} 序列为例讲解两种查找最值的算法,一种是普通算法,另一种是借助 分治算法解决。 普通算法 普通算法的解决思路是:创建两个变量 max 和 min 分别记录数组中的最大值和最小值,它们的初始值都