在排序数组中找到绑定给定值的两个连续值的优雅方法?

时间:2010-08-26 16:50:45

标签: algorithm collections

我有一个排序整数的数组,我想得到两个连续的元素索引,它们绑定了我传入的特定值。为了说明,因为很难用文字描述,让我们说我有一个数组(常规零索引):

1 3 4 5 7 9

我想得到两个绑定的索引,例如值6.在这种情况下,数组在连续位置具有值5和7,这限制了我正在寻找的值(5 <= 6&lt; ; = 7),所以我将返回索引5和索引7(分别为3和4)。

我目前以非常强力的方式实现这一点,涉及阵列中的大量排序和搜索。另外,我觉得我错过了很多极端情况(尤其是值大于/小于数组中最大/最小值的值)。

有一种优雅的方式吗?我应该注意哪些角落的案例,我该如何处理和/或检查它们?谢谢!

4 个答案:

答案 0 :(得分:3)

您可以使用二分搜索解决问题,在O(lg(n))中解决问题,而不考虑这么多边界情况。我们的想法是使用二进制搜索来查找大于或等于要绑定的值的最低元素(让我们称之为x)。

pair<int, int> FindInterval(const vector<int>& v, int x) {
  int low = 0, high = (int)v.size();
  while (low < high) {
    const int mid = (low + high) / 2;
    if (v[mid] < x) low = mid + 1;
    else high = mid;
  }
  // This if is used to detect then a bound (a <= x <= x) is impossible but a
  // bound (x <= x <= can be found).
  if (low == 0 && low < (int)v.size() && v[low] == x) ++low;
  return make_pair(low - 1, low);
}

请注意,答案可能是(-1, 0),表示该时间间隔没有下限,可能是(n - 1, n),表示该时间间隔没有上限(其中{{1}是} n)的大小。此外,如果v位于x,则可能有两种可能的答案;如果v多次x,则可能有多个答案,因为边界包含极值。

最后,您可以使用v函数替换二进制搜索:

std::lower_bound

答案 1 :(得分:2)

基本上:

  1. 对数组进行排序(一次);
  2. 进行二分搜索以找到最接近的元素;
  3. 将该元素与输入值进行比较;
    • 如果它更低,则有下限;
    • 如果它越高,你就越高;
    • 如果它是相同的,那么边界就在元素旁边。
  4. 现在,如果你可以在数组中有重复值,那么最后一步就会复杂一些。您可能需要跳过几个值。

    最终,这只是对排序数组进行二分搜索,排序数组中的O(log n)和未排序数组上的O(n log n)也是如此。

答案 2 :(得分:1)

二进制搜索您想要的值(在本例中为6)。

如果找到,请根据结果索引获取上一个和下一个值。

如果没有,您的最终搜索值将小于 或大于目标值。如果它更大,则您的边界值将位于该索引处和前一个索引处。否则,他们将在那个索引和下一个索引。

答案 3 :(得分:0)

提高速度的一种方法是使用binary search。这会将 O(n)的当前时间复杂度降低到 O(log n)