3

任务——这个代码问题的目标是实现二分搜索算法。

输入格式——输入的第一行包含一个整数 n 和一个序列 a0 < a1 < ... < an−1,其中 n 对不同的正整数按递增顺序排列。下一行包含一个整数 k 和 k 个正整数 b0,b1,...,bk−1。

约束——1≤n,k≤10^4;1 ≤ a[i] ≤ 10^9 对于所有 0 ≤ i < n;1 ≤ b[]j ≤ 10^9 对于所有 0 ≤ j < k;

输出格式——对于从 0 到 k−1 的所有 i,输出一个索引 0 ≤ j ≤ n−1 使得 aj = bi 或 -1 如果没有这样的索引。

我正在使用带有 c++11 编译器的代码块。我已经尝试过压力测试并在我的系统中得到了正确的结果。但是 coursera autograder 给了我未知的信号 11。在某些问题中它给出了未知的信号 8。谁能告诉我这背后的可能原因。

int binary_search(const vector<long long> &a, long long x) {
  size_t left = 0, right = (size_t)a.size()-1;
  size_t mid = 0;
  while(left<=right){
    mid = (left+right)/2;
    if(x < a[mid]){
        right = mid-1;
    }
    else if(x > a[mid]){
        left = mid+1;
    }
    else return mid;
  }
  return -1;
}
int main() {
  size_t n;
  std::cin >> n;
  vector<long long> a(n);
  for (size_t i = 0; i < a.size(); i++) {
    std::cin >> a[i];
  }
  size_t m;
  std::cin >> m;
  vector<long long> b(m);
  for (size_t i = 0; i < m; ++i) {
    std::cin >> b[i];
  }
  for (size_t i = 0; i < m; ++i) {
    //replace with the call to binary_search when implemented
    std::cout << binary_search(a, b[i]) << ' ';
  }
}

我在自动评分机中得到的实际结果。

Failed case #4/36: unknown signal 11 (Time used: 0.00/1.00, memory used: 40071168/536870912.)
4

3 回答 3

4

如果向量的大小为 2 ,则初始化left = 0和。所以你计算并检查是否。如果发生这种情况,您现在设置. 在无符号算术中,这是一个非常大的数字。您的循环继续,因为您计算并访问那里的向量。那是UB,会让你的程序被杀死。right = 1mid = 0left <= rightmid = 0x < a[0]right = -10 <= really large numbermid = half of really large number

切换到有符号类型意味着right = -1确实小于left = 0并终止循环。

于 2019-06-06T08:32:52.213 回答
2

不了解 Coursera 测试用例,但您的代码肯定会因两个极端情况而失败:

1) 空输入向量a-> 你会在 line 中得到下溢right = (size_t)a.size()-1;。换句话说,right将成为一个大的正值,你将进入循环并尝试检索一些大的正索引a[mid]在哪里。mid当然,尝试从空数组中获取它会导致错误。

2)left+right太大->溢出->在许多二进制搜索实现中发现的错误,甚至在书籍中:)改用mid = (right - left) / 2 + left

于 2019-06-06T07:39:25.863 回答
0

通过将 all 更改size_tlong,它可以正常工作。未知信号 11表示分段错误,即内存访问有问题。因此,更改所有内容size_tlong增加范围,vector从而让适合更多的值,从而解决内存访问问题。

于 2019-06-06T08:19:58.160 回答