二进制砍: if list[middle] == key case
我正在修改考试的算法,我试图解决这个练习,但我无法想出解决方案。
这是伪代码。
1. int search (int [] a, int x) {
2. // Pre: ∃i:Nat (0≤i<a.length ∧ a[i]=x) ∧ a is in ascending order
3. // Post: 0≤ r≤ a.length ∧
4. // ∀i:int.(0 ≤ i < r → a[i] < x) ∧ a[r]=x
5. int left, middle; int right = a.length;
6. if (a[0]>=x) return 0; else left=0; //a[left]<x (a)
7. while ((right-left>1){ (b)
8. // invariant: (I1) 0≤ left < right ≤ a.length ∧
9. // (I2) ∀i:int(0 ≤ i ≤ left → a[i] < x) ∧
10. // (I3) ∀i:int(right ≤ i < a.length → a[i] > x)
11. // (note: a[i]>x not a[i]≥x)
12. // Variant: right-left-1
13. middle = (left+right) / 2; // left < middle < right (*)
14. if ( a[middle]== x) return middle;
15. else {if a[middle)<x) left = middle ;
16. else right=middle;} (c)
17. }
18. } // left+1=right } (d)
因此,现在的代码不满足后置条件,因为对于某些输入(例如 x = 1 和 a={0,1,1,1,1}),第 14 行返回的值不满足第 4 行的后置条件。 该练习要求: 将第 14 行的“return middle;”替换为 while 循环并 return 代码,使其满足后置条件。包括变体和 不变性强到足以暗示 返回后置条件。提示:请确保您包含了未更改的内容。”
我一直无法找到解决方案。 有人可以帮助我吗?
提前致谢, 主播
编辑: 好的,谢谢两位的帮助。
while(middle > 0 && a[middle] == x){
middle--;
} 返回中间;
我选择了中间的变体。不变式是:
0x
你认为这是正确的吗?
I'm revising algorithms for my exams and I was trying to solve this exercise but I couldn't come up with a solution.
This is the pseudo-code.
1. int search (int [] a, int x) {
2. // Pre: ∃i:Nat (0≤i<a.length ∧ a[i]=x) ∧ a is in ascending order
3. // Post: 0≤ r≤ a.length ∧
4. // ∀i:int.(0 ≤ i < r → a[i] < x) ∧ a[r]=x
5. int left, middle; int right = a.length;
6. if (a[0]>=x) return 0; else left=0; //a[left]<x (a)
7. while ((right-left>1){ (b)
8. // invariant: (I1) 0≤ left < right ≤ a.length ∧
9. // (I2) ∀i:int(0 ≤ i ≤ left → a[i] < x) ∧
10. // (I3) ∀i:int(right ≤ i < a.length → a[i] > x)
11. // (note: a[i]>x not a[i]≥x)
12. // Variant: right-left-1
13. middle = (left+right) / 2; // left < middle < right (*)
14. if ( a[middle]== x) return middle;
15. else {if a[middle)<x) left = middle ;
16. else right=middle;} (c)
17. }
18. } // left+1=right } (d)
So, the code as it is now doesn't satisfy the post condition because for certain inputs (e.g. x = 1 and a={0,1,1,1,1}) the value returned by line 14 doesn't satisfy the post-condition on line 4.
The exercise is asking to :
"Replace "return middle;" on line 14. by a while loop and return
code so that it satisfies the postcondition. Include variant and
invariant strong enough to imply the
postcondition on return. Hint: Make sure you include to state what doesn't change."
I have not been able to find a solution.
Can anyone help me?
Thanks in advance,
VJ
EDIT:
Ok, thank you both of you for your help.
while(middle > 0 && a[middle] == x){
middle--;
}
return middle;
I chose the variant to be middle. And the invariant to be :
0x
Do You reckon this is correct?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当 a[middle] = x 时,如果 middle 之前有相同的值,我们确信我们应该返回索引 middle 或它之前的内容。
但这
可能会很慢,例如,当整个 a 包含相同的值时,它具有线性时间复杂度。
When a[middle] = x we are sure we should return index middle or something before it, if there are the same values before middle.
So
But that can be slow, for example when whole a contains the same values it has linear time complexity.
Ajuc 发布了一个使用循环的解决方案,但正如他所说,这可能很慢。
更快的方法是再次对左侧数组使用二分搜索。如果没有找到则返回 i,否则返回二分查找的结果。复杂度将保持不变 (O(logn))。
因为这看起来像家庭作业,我会让你自己解决剩下的:)。
Ajuc has posted a solution using a loop, but as he said this can be slow.
A faster approach is to again use binary search on the left array. If it is not found return i, else return the result of this binary search. The complexity will remain the same (O(logn)).
Since this looks like homework I will let you figure out the rest by yourself :).