我想在排序数组中插入一个元素(替换现有元素)
[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;
}
我错过了什么,我如何证明我所做的事情会导致总是正确的结果?
答案 0 :(得分:3)
我通常做的事情,我认为证明算法正确的最简单方法是将其视为最小单位。因此,首先给出一个算法可能会失败并测试它是否会失败的场景。
假设first = 0
和last = 1
。然后,mid = (0 + 1 )/ 2 = 0
。所以有3种可能的情况。
a[mid] == x
,那么很棒,你就找到了答案。a[mid] > x
时,您将移动last = mid - 1 = -1
。太棒了,你终止了因为last
不大于first
而且它是真的,因为x
小于排序列表的第一个元素的值,所以{{1}是不可能的在列表中。x
时。那么你将移动你的a[mid] < x
。现在,在这种情况下,您终止循环。但是,有一些问题,因为first = mid + 1 = 1
可能具有您所寻找的价值。您只需跳过一个可能的选项。以下是算法失败时的可视化情况。假设a[1]
并表示x = 5
和F = first
。
(1 5) 6 7 8 9 15 ^ ^ F L
如您所见,粗体部分是可能的选项。在L = last
和a[0]
时,您有两个可能的选项a[1]
和first = 0
。然后,当您计算last = 1
时以及检测到mid = (0 + 1) / 2 = 0
时。然后移动a[mid] = a[0] = 1 < 5
和first = 1
。您终止循环,因为last = 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
时,我返回-1。因此,您只需以这种方式创建函数x
。
replace
答案 1 :(得分:1)
请注意您的代码。如果你想用0,2,3,4,5中的6替换5。 第一次迭代:first = index 0,last = index 4,mid = index 2. 3&lt; 6所以现在首先是索引3,最后是4。下一次迭代:第一=索引3,最后=索引4,中=索引3. 4&lt;因此,现在首先是指数4. 4!&lt; 4,所以去,如果,否则。 a [4]是5,5&lt; 5。 6,所以返回第一个+ 1,这是索引5.该索引现在超出界限。
你需要确保你没有超出范围。如果你有数字1 2 4 5并且你想要插入3.你会做什么,覆盖2或4?都工作。您将通过您的代码自动替换4,但是您是否总是想要替换更高的数字,也许您想要做最接近的数字?这只是需要考虑的事情。
答案 2 :(得分:1)
我建议您对原始代码进行一些修改,然后您可以确保您的代码始终能够提供正确的结果:
以下是我的代码版本:
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。 为此,一旦我们走出循环,我们需要考虑“开始”的最终价值。变量。如果它等于数组的大小,那么新元素就会结束。我已相应更新了代码。