【问题标题】:binary search on c, the while loopc 的二分查找,while 循环
【发布时间】:2016-06-18 08:09:40
【问题描述】:

在 C 语言的二进制搜索代码中有一些我没有得到的东西。

int binarySearch(int a[], int n, int x)
{
   int low=0, mid, high=n-1;
   while(low <= high)
   {
        mid = (low + high) / 2;
        if (x < a[mid])
            high = mid - 1;
        else if (x > a[mid])
         low = mid + 1;
       else
         return mid;
   }
   return -1;
}

为什么while循环while(left&lt;=right)写不出来: while(left&lt;right)? 这种变化会影响事情吗?

【问题讨论】:

  • 没有完整的代码,这很难说。
  • 我已经添加了代码。
  • 我有,我可以看到它不起作用,但我想了解原因,谢谢。
  • 真的在问“&lt;&lt;= 不同吗?”
  • @Olaf 好吧,我可以想到两种变体的算法行为相同。所以问题是“&lt;&lt;= 的算法是否相同”

标签: c search binary


【解决方案1】:

举个简单的例子

int a[1] = {5};
printf("%d\n", binarySearch(a, 1, 5));

使用while(low &lt; high),代码打印-1(未找到 - 错误答案)。

使用while(low &lt;= high),代码打印 0(找到 - 正确答案)。

【讨论】:

  • 简单地单步执行包含一个元素的数组的代码肯定会说明为什么&lt; 失败` 而&lt;= 有效。
【解决方案2】:

第 1 部分 - 快速回答这个特定问题

这不是对二分搜索的完整总结,但我会简短地解决这个问题。
这两个 while 循环条件的主要区别,给定
1. low(left) 和 high(right) 指针相应更新。 “相应地”,请参阅第 3 部分。
2.假设LOW(LEFT)和HIGH(RIGHT)的边界没有重复
3. 假设目标存在于数组

while(low &lt;= high) 在[LOW,HIGH]的范围内进行搜索,包括两端。
相比之下,while(low &lt; high) 在 [LOW, HIGH) 范围内进行二分搜索,右/高端独占。对于上/右范围/部分中的目标的二进制搜索,他们总是错过最后/右/高的检查,最后一个low(left) 停止。为了使范围完全覆盖,通常建议根据最后一个low(left) 指针进行另一个判断。


第 2 部分 - 一般准则

可能是任意的一般准则:
1. 处理数组中肯定存在目标,且搜索的数组不包含重复的情况时,首选while(low &lt;= high)
2.在处理数组中不一定存在target,且数组可能包含重复的情况时,推荐while(low &lt; high)

第 3 部分 - 代码

low(left) 和 high(right) 指针“相应”更新

    public int binarySearch(int[] nums, int target){

        int left = 0, right = nums.length - 1;
        // please pay attention to the initial condition of right(ptr)
        while(left <= right){
            // to floor the mid
            int mid = left + (right - left) / 2;

            // to check whether the middle element is equal to the target in every iteration
            if(nums[mid] == target) return mid;
            else if(target > nums[mid]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }

        return -1;
    }
    public int binarySearch(int[] nums, int target){
        // please pay attention to the initial condition or the right(ptr)
        int left = 0, right = nums.length;

        while(left < right){
            int mid = left + (right - left) / 2;

            // please pay twice attention to the equality case
            if(target > nums[mid]) {
                left = mid + 1;
             } else {
                right = mid;
             }
        }

        return left;
    }

第 4 部分 - 变体,更高级

警告:可能会引起混淆
对于while(low &lt;= high)的类型:

    public int binarySearchWithFlooringMid(int[] nums, int target){
        // please pay attention to the initial condition of right(ptr)
        int left = 0, right = nums.length - 1;
        while(left <= right){
            // to floor the mid
            int mid = left + (right - left) / 2;

            // to check whether the middle element is equal to the target in every iteration
            if(nums[mid] == target) return mid;
            else if(target > nums[mid]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        return -1;
    }

    public int binarySearchWithCeilingMid(int[] nums, int target){
        int left = 0, right = nums.length - 1;
        while(left <= right){
            // to ceil the mid
            int mid = left + (right - left + 1) / 2;

            // to check whether the middle element is equal to the target in every iteration
            if(nums[mid] == target) return mid;
            else if(target > nums[mid]) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }

        return -1;
    }

对于while(low &lt; high)的类型

    public int binarySearchLeftmost(int[] nums, int target){
        int left = 0, right = nums.length;

        while(left < right){
            int mid = left + (right - left) / 2;

            // please pay twice attention to the equality case
            if(target > nums[mid]) {
                left = mid + 1;
             } else {
                 right = mid;
             }
        }

        return left;
    }

    public int binarySearchRightmost(int[] nums, int target){
        int left = 0, right = nums.length;

        while(left < right){
            int mid = left + (right - left) / 2;

            // please pay twice attention to the equality case
            if(target < nums[mid]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }

        return right - 1;
    }

这篇文章并未涵盖二进制搜索方面的所有情况。还有更复杂的需求,等我掌握了再细讲。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多