带重复项的二分查找

Binary Search with Duplicates

我正在做这个特殊的练习,我必须实现二进制搜索算法,该算法 returns 排序数组中元素第一次出现的索引,如果它包含重复项。由于我主要在 C++ 中研究我的算法技能,所以我只尝试在 C++ 中进行。这是我的代码:

#include <iostream>
#include <cassert>
#include <vector>

using std::vector;

int binary_search(const vector<int> &a, int x, int n) {
  int left = 0, right = n-1; 

  while(left<= right){
    int mid = left + (right-left)/2;
    if(x== a[mid]){
      return mid;
    }else if(a[mid]>x){
      right = mid-1;
    }else{
      left = mid+1;
    }
  }
      return -1;
}


int first_occurence(const vector<int>&a, int x, int n) {
  int out = binary_search(a, x, n);
  if(out !=-1){
     for(int i = out;i>0&& a[i]==x;--i ){
        out = i;
     }
  }
  return out;
}

int main() {
  int n;
  std::cin >> n;
  vector<int> a(n);
  for (size_t i = 0; i < a.size(); i++) {
    std::cin >> a[i];
  }
  int m;
  std::cin >> m;
  vector<int> b(m);
  for (int i = 0; i < m; ++i) {
    std::cin >> b[i];
  }
  for (int i = 0; i < m; ++i) {
    std::cout << first_occurence(a, b[i], n) << ' ';
  }
}

程序的第一个输入告诉数组应该包含多少项,第二个是这些元素的枚举,第三行告诉要搜索多少个键,最后一行是单个键。输出是键的索引,如果找不到这样的键,则输出 -1。

我的策略是使用函数查找键的索引。如果找到,则在重复的情况下,第一次出现的索引必须较低。这就是 first_occurence() 方法的作用;继续循环直到找到第一个出现的地方。

对于以下输入:

10
1 5 4 4 7 7 7 3 2 2
5
4 7 2 0 6

输出为:

-1 4 -1 -1 -1

这只对密钥 7 是正确的。我已经尝试调试它很长时间了,但我无法找出问题所在。

returns the index of the first occurence of an element in a sorted array,

您的二进制搜索算法要求在您调用它之前对数据进行排序

示例:

#include <algorithm>
#include <sstream>

int main() {
    std::istringstream in(R"aw(10
1 5 4 4 7 7 7 3 2 2
5
4 7 2 0 6
)aw");

    int n;
    in >> n;
    vector<int> a(n);
    for (auto& v : a) {
        in >> v;
    }

    std::sort(a.begin(), a.end());               // <- add this

    // display the sorted result:
    for (auto v : a) std::cout << v << ' ';
    std::cout << '\n';

    int m;
    in >> m;
    vector<int> b(m);
    for (auto& v : b) {
        in >> v;
    }
    for (auto v : b) {
        std::cout << v << ' ' << first_occurence(a, v, n) << '\n';
    }
}