【问题标题】:I want a recursive function to check the order of an array using binary search我想要一个递归函数来使用二进制搜索检查数组的顺序
【发布时间】:2016-11-15 15:36:36
【问题描述】:

我写了一个递归函数来检查一个大小为 n 的数组是否按升序排列:

bool sortedAscending(const int*x, int n){
if (n == 0) return true;
if (x[n - 1] >= x[n - 2]) sortedAscending(x, n - 1);
else return false;
}

我想做同样的工作,但使用二分搜索算法(即每次递归调用将数组分成两半......)。我怎样才能做到这一点? 谢谢。

【问题讨论】:

  • 递归函数应该使用一对迭代器——一个在它应该检查的范围的开头和一个结尾。然后你可以轻松地递归调用它,只需将范围减半。
  • 两个问题。 (1) if (n <= 1) return true; - 一个元素的数组总是排序的;以下代码假定至少有两个元素。 (2) return sortedAscending(x, n - 1); - 您缺少 return 声明。另外,最后两行可以简化为return x[n - 1] >= x[n - 2] && sortedAscending(x, n - 1);
  • 但是每次拆分时我比较什么值?
  • 为什么要使用效率较低的方法?
  • 我不确定“二进制搜索”方法在检查数组是否已排序时是否有意义。无论如何,您都必须查看每个元素,因此直接遍历数组可能会更快。你想把它作为一个练习来做还是你认为它会更快?

标签: c++ recursion binary-search


【解决方案1】:
bool sortedAscending(const int* x, int n) {
  if (n <= 1) return true;
  int m = n / 2;
  return x[m-1] <= x[m] &&
         sortedAscending(x, m) &&
         sortedAscending(x + m, n - m);
}

【讨论】:

  • 这是 O(n) 的时间复杂度吗?
  • 是的。你期待不同的东西吗?
  • 但我们不是每次都分一半吗?不应该是 O(log2(n)) 吗?
  • 每个部分的长度只有一半 - 但您现在要检查其中的两个,因此工作量保持不变。这种方法只是重新排列进行比较的顺序 - 它仍然进行n-1 比较。根本没有办法检查数组是否以较少的比较排序 - 一旦你跳过一个,我可以在你不注意的情况下交换这两个元素。
  • 实际上,这可能比通过数组的正常循环还要慢,因为您可以通过索引周围的“随机”跳转来防止预取。
【解决方案2】:

我更喜欢使用指向候选数组开始和结束的指针。这更符合迭代器的风格。

#include <iostream>

bool sortedAscending(const int* start, const int* end)
{
    if(start == end) return true;
    if(start + 1 == end) return true;
    auto halfDiff = (end - start) / 2;
    return *(start + halfDiff - 1) <= *(start + halfDiff) && sortedAscending(start, start + halfDiff) && sortedAscending(start + halfDiff, end);
}

int main()
{
    int array1[] = {0,1,2,3,4,5,6,7};
    int array2[] = {0,1,3,2,4,5,6,7};
    int array3[] = {0};
    int* array4 = nullptr;

    std::cout << "Array1: " << sortedAscending(std::begin(array1), std::end(array1)) << std::endl;
    std::cout << "Array2: " << sortedAscending(std::begin(array2), std::end(array2)) << std::endl;
    std::cout << "Array3: " << sortedAscending(std::begin(array3), std::end(array3)) << std::endl;
    std::cout << "Array4: " << sortedAscending(array4, array4) << std::endl;

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2019-01-19
    • 2015-09-28
    • 1970-01-01
    相关资源
    最近更新 更多