【问题标题】:insert an element into a sorted array using binary search使用二分搜索将元素插入排序数组
【发布时间】:2014-01-21 00:21:46
【问题描述】:

我想在排序数组中插入一个元素(替换现有元素)

[1, 2, 3, 4, 5]

例如插入 0 并保持它应该替换 1 的顺序

[0, 2, 3, 4, 5]

并插入 6 并保持它应该替换 5 的顺序

[0, 2, 3, 4, 6]

我想使用二分搜索,我创建了以下内容

int binary_search(int *a, int first, int last, int x) {

    int mid;

    while (first <= last) { /* was <, changed to <= */

        mid = (first + last) / 2;

        if (a[mid] == x)
            return mid;

        else if (a[mid] > x)
            last =  mid - 1;

        else
            first = mid + 1;
    }

    /* after the loop => first = last */

    if (a[first] > x)
        return first;
    else
        return first + 1;
}

我是否遗漏了什么?我如何证明我所做的会导致始终正确的结果?

【问题讨论】:

标签: binary-search


【解决方案1】:

我通常做的并且我认为证明算法正确的最简单方法是将其视为最小单位。因此,让我们先给出一个算法可能会失败的场景并测试它是否会失败。

假设first = 0last = 1。然后,mid = (0 + 1 )/ 2 = 0。所以有3种可能的情况。

  • a[mid] == x,那就太好了,你找到了答案。
  • a[mid] &gt; x,那么你将移动你的last = mid - 1 = -1。太好了,您终止了,因为last 不大于first,这是因为x 小于排序列表的第一个元素的值,所以x 不可能在列表中。
  • a[mid] &lt; x。然后您将移动您的first = mid + 1 = 1。现在,在这种情况下,您终止循环。但是,有一些问题,因为a[1] 可能持有您正在寻找的价值。您只需跳过一个可能的选项。

以下是您的算法失败时的可视化情况。假设x = 5 并表示F = firstL = last

(1 5) 6 7 8 9 15 ^ ^ F L

如您所见,粗体部分是可能的选项。当first = 0last = 1 时,您有两个可能的选项,即a[0]a[1]。然后,当您计算 mid = (0 + 1) / 2 = 0 并检测到 a[mid] = a[0] = 1 &lt; 5 时。然后你移动你的first = 1last = 1。您终止循环,因为last 不再大于first,在这种情况下,您只检查a[0],但您跳过a[1]


所以我建议这样做

def binarysearch(a, x):
    low  = 0
    high = length(a)

    while low <= high:
        mid = (high + low) / 2
        if     (a[mid] == x): return mid
        elseif (a[mid] > x) : low  = mid + 1
        else                : high = mid - 1

    return -1

在您的代码中,您没有机制来判断您正在搜索的项目是否未找到。当找不到 x 时,我返回 -1。因此,您可以通过这种方式简单地创建函数replace

def replace(a, x, y):
    # replace x with y 
    i = binarysearch(a, x)
    if i >= 0:
        a[i] = y
    else:
        print "x does not exist"

【讨论】:

【解决方案2】:

请注意您的代码。如果要在 0、2、3、4、5 中将 5 替换为 6。 第一次迭代:第一个 = 索引 0,最后一个 = 索引 4,中间 = 索引 2。3

您需要确保自己不会越界。另外,如果你有数字 1 2 4 5 并且你想插入 3。你会怎么做,覆盖 2 或 4?两者都有效。您将通过您的代码自动替换 4,但您是否总是想替换较大的数字,也许您想替换最接近的数字?这只是需要考虑的事情。

【讨论】:

    【解决方案3】:

    我想建议对您的原始代码进行一些修改,然后您可以确定您的代码将始终给出正确的结果:

    1. 在while循环中,你写了while(first
    2. 在while循环之后,我们需要添加一个检查a[first](或a[last])是否等于x。如果是,则只需返回此索引的值。
    3. 如果 a[first] > x,则 x 可以插入到位置 'first'。
    4. 如果 a[first]

    这是我的代码版本:

    int binary_search(vector<int> a, int first, int last, int x) {
        int mid;
        while (first < last) {
            mid = (first + last) / 2;
            if (a[mid] == x)
                return mid;
            else if (a[mid] > x)
                last =  mid - 1;
            else
                first = mid + 1;
        }
        if (start == a.size())
            return a.size();
        else if(a[first] > x)
            return first;
        else
            return first+1;
    }
    

    编辑:假设我们希望在 {1,3,5,6} 中插入 7。 为此,一旦我们退出循环,我们需要考虑“开始”变量的最终值。如果它等于数组的大小,则新元素在最后。我已经相应地更新了代码。

    【讨论】:

      猜你喜欢
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 2014-06-22
      • 2014-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多