【问题标题】:What am I doing wrong in my C binary search code?我在 C 二进制搜索代码中做错了什么?
【发布时间】:2020-10-06 05:01:38
【问题描述】:

我正在研究二进制搜索算法以准备我的编码面试,但是我的算法仅适用于最佳情况,即当搜索的数据处于中点时,O(1)。当我将值更改为更坏的情况时,光标卡住了,比如第一个位置。

我知道二进制搜索有一个 O(log n) 更坏的情况,所以它不应该花很长时间。我做错了吗?

#include <stdio.h>

int binary_search(int arr[], int left, int right, int data){
    // condition that runs only if true
    while(left <= right){
        int mid = (left + right) / 2;
        if(data == arr[mid]){
            return mid;
        }

        if(data > arr[mid]){
            binary_search(arr, mid+1, right, data);
        }

        binary_search(arr, left, mid-1, data);
    }
    return -1;
}

void main(){
    int arr[] = {1,2,3,4,5,6,7,8,9};
    int result = binary_search(arr, 0, (sizeof(arr)/sizeof(arr[0]) - 1), 2);
    (result == -1) ? printf("There was no record found\n") : printf("Your record was found at position %d\n", result+1);
}

【问题讨论】:

  • 你应该返回递归调用的返回值。
  • 模糊的观察:递归很少是做某事的最快方法,即使做得正确。 main() 必须返回 int
  • @RobertHarvey 问题标题是“我在 C 二进制搜索代码中做错了什么?”
  • 不,问题是“当我将值更改为更坏的情况时,光标卡住了,比如第一个位置。”
  • @Vik 有趣的是,面试的职位是什么?:) 项目经理的职位?

标签: c arrays algorithm binary-search function-definition


【解决方案1】:

您的函数未正确返回,从而触发了无限递归。 在递归调用binary_search(arr, mid+1, right, data); 的地方,需要将返回值传播回调用函数。

此外,与您的问题无关,但在 C 中 void main() 在技术上是不合法的,即使您可能没有得到任何明确的错误。 main() 应该总是返回一个 int。

#include <stdio.h>

int binary_search(int arr[], int left, int right, int data){
    // condition that runs only if true
    while(left <= right){
        int mid = (left + right) / 2;
        if(data == arr[mid]){
            return mid;
        }

        if(data > arr[mid]){
            return binary_search(arr, mid+1, right, data);
        }

        return binary_search(arr, left, mid-1, data);
    }
    return -1;
}

int main(void){
    int arr[] = {1,2,3,4,5,6,7,8,9};
    int result = binary_search(arr, 0, (sizeof(arr)/sizeof(arr[0]) - 1), 2);
    (result == -1) ? printf("There was no record found\n") : printf("Your record was found at position %d\n", result+1);

    return 0;
}

【讨论】:

  • 实际上,挑剔一点,递归是有限的 - 子数组减半 - 但除非匹配,否则 OP 的循环永远不会终止。
  • @500-InternalServerError 不错!实际上,这在技术上是一个无限循环。
【解决方案2】:

如果在第一次迭代中data 不等于arr[mid],则您的代码不起作用,因为您的递归函数不返回任何内容。所以在这种情况下,你将有一个无限递归。

但无论如何对于专业程序员来说,代码非常非常弱。

例如,您的函数可能不会为常量数组调用。 (是否需要另外一个名称不同的函数?)

函数应该只有三个参数

return_type binary_search( const int a[], size_t n, int data );

如果函数返回目标元素的索引,则其返回类型应为size_t,因为通常int 类型无法容纳表达式sizeof( a ) / sizeof( *a ) 的值。

如果函数只检查给定值是否存在于数组中,则它应返回01,其返回类型应为int_Bool

如果函数应该返回目标值的位置,那么它应该返回具有目标值的元素的第一个位置,其方式与 C++ 中的标准算法 std::lower_bound 相同。

复制标准 C 函数 bsearch 的相同缺点不是一个好主意,通常也不返回第一个元素的位置和目标值。

您不应使用运算符 == 来比较值(尽管 C 中的比较函数使用此运算符),因为例如对于浮点数,您可能会得到错误的结果。您应该只使用运算符 <.>

好吧,让我们假设您的函数适用于元素类型为int 和运算符

第二个问题,如果用户要使用元素类型为long long 的数组或结构数组,他是否需要花时间再编写一个二分查找函数?

我的建议:不要在面试中做任何作业。忽略那些试图操纵你和你的时间的公司。面试是平等伙伴的对话。只要您自己是一名合格的程序员,在简单的对话中就很容易理解“谁是谁”。 :)

【讨论】:

    猜你喜欢
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-05
    • 1970-01-01
    相关资源
    最近更新 更多