halting proof of binary search - algorithm

l = -1; u = n;
while l+1 != u
m = l + (u-l)/2;
if x[m] < t
l = m;
else
u = m;
p = u;
if p >= n || x[p] != t
p = -1;
We assume x[-1] < t and x[n] >= t and n >= 0 in the above code.
The above code is a modified binary search which can return the first occurrence of the integer t in the integer array x[0..n-1] instead of returning a random one.
My question is like this:
Why do the above code always halt? Can anyone explain it or prove it?
Thanks,

Because on every iteration, the gap between l and u halves, within the constraints of integer arithmetic. All sequences of (positive) integer halving must eventually reach 1, which is the termination condition.

Related

How to construct and justify loop invariant, which allows to show partial correctness

I need to construct and justify a loop invariant with given specification:
{n > 0} P {q = | {j: a[j]=x and 0 <= j < n} |}
where |A| is a number of elements of set A. It means that q is equal to the number of elements from array a that are equal to x.
Code P is specified as:
{
int i = 0, q = 0;
while (i != n){
if (a[i] == x)
q = q + 1;
i = i + 1;
}
I know that loop invariant must be true:
before the loop starts
before each iteration of the loop
after the loop terminates
but I have no clue how should I find the right loop invariant, that would allow me to show partial correctness of P afterwards. I already tried to look at every single iteration of the loop and variables for random n, x and a[0...n-1] to see which values combined are constant while the loop is working, but it did not help.
Look at your code carefully. At the beginning, q is 0, and it only grows when you find new elements that are == x. So
q = | {j: a[j]=x and 0 <= j < i} |
is part of your invariant. Note that in your specification, you had < n instead of < i. Notice also that, at loop termination, i == n. So it will also be valid at the start. It will also be true at any point in between: so far, so good. Is anything else missing? Yes, we should also state that
0 <= i <= n -- because that describes the range of values of i (otherwise, i would be free to venture outside the array).
Is this all? Yes -- there is no other loop state left to describe. Therefore, your complete invariant looks like
q = | {j: a[j]=x and 0 <= j < i} | and 0 <= i <= n
When solving these exercises, you can try these 2 steps:
try to describe in plain text what goes on in the algorithm: "I sweep i from 0 to n-1, stopping at n, and at every moment, I keep in q the amount of x that I have found within the array". All variables involved in the loop must be mentioned!.
translate that plain text into math, while also making sure that your post-condition is reflected in the invariant, generally replacing the n by the loop counter (in this case, i)
As a thought experiment, try to write the invariant with the equivalent loop (but iterating from the end to the beginning) instead:
{
int i = n-1, q = 0;
while (i >= 0){
if (a[i] == x)
q = q + 1;
i = i - 1;
}
Mouse over for answer (but try to figure it out first).
q = | {j: a[j]=x and i < j < n} | and -1 <= i < n
Note the different limits, reflecting that i sweeps differently;
but the same overall structure

How does this method, which finds the smallest factor of a given number, work?

I've recently come across a method which returns the smallest factor of a given number:
public static int findFactor(int n)
{
int i = 1;
int j = n - 1;
int p = j; // invariant: p = i * j
while(p != n && i < j)
{
i++;
p += j;
while(p > n)
{
j--;
p -= i;
}
}
return p == n ? i : n;
}
After examining the method, I've been able to (most likely incorrectly) determine the quantities which some of is variables respectively represent:
n = the int that is subject to factorization for
the purposes of determining its smallest factor
i = the next potential factor of n to be tested
j = the smallest integer which i can be multiplied by to yield a value >= n
The problem is I don't know what quantity p represents. The inner loop seems to treat (p+=j) - n as a
potential multiple of i, but given what I believe j represents, I don't understand how that can be true
for all i, or how the outer loop accounts for the "extra" iteration of the inner loop that is carried out
before the latter terminates as a result of p < n
Assuming I've correctly determined what n, i, and j represent, what quantity does p represent?
If any of my determinations are incorrect, what do each of the quantities represent?
p stands for “product”. The invariant, as stated, is p == i*j; and the algorithm tries different combinations of i and j until the product (p) equals n. If it never does (the while loop falls through), you get p != n, and hence n is returned (n is prime).
At the end of the outer while loop's body, j is the largest integer which i can be multiplied by to yield a value ≤ n.
The algorithm avoids explicit division, and tries to limit the number of j values inspected for each i. At the beginning of the outer loop, p==i*j is just less than n. As i is gradually increased, j needs to gradually shrink. In each outer loop, i is increased (and p is corrected to match the invariant). The inner loop then decreases j (and corrects p) until p is ≤ n again. Since i*j is only just less than n at the beginning of the next outer loop, increasing i makes the product greater than n again, and the process repeats.
The algorithm tries all divisors between 1 and n / i (continuing past n / i is of no use as the corresponding quotients have already been tried).
So the outer loop actually performs
i= 1
while i * (n / i) != n && i < n / i)
{
i++;
}
It does it in a clever way, by avoiding divisions. As the annotation says, the invariant p = i * j is maintained; more precisely, p is the largest multiple of i that doesn't exceed n, and this actually establishes j = n / i.
There is a little adjustment to perform when i is incremented: i becoming i + 1 makes p = i * j become (i + 1) * j = p + j, and p may become too large. This is fixed by decrementing j as many times as necessary (j--, p-= i) to compensate.

Finding Numbers where modulo is k

I have given a Number A where 1<=A<=10^6 and a Number K. I have to find the all the numbers between 1 to A where A%i==k and i is 1<=i<=A. Is there any better solution than looping
Simple Solution
for(int i=1;i<=A;i++)
if(A%i==k) count++;
Is there any better solution than iterating all the numbers between 1 to A
The expression A % i == k is equivalent to A == n * i + k for any integer value of n that gives a value of A within the stated bounds.
This can be rearranged as n * i = A - k, and can be solved by finding all the factors of A - k that are multiples of i (where k < i <= A).
Here are a couple of examples:
A = 100, k = 10
F = factor_list(A-k) = factor_list(90) = [1,2,3,5,6,9,10,15,18,30,45,90]
(discard all factors less than or equal to k)
Result: [15,18,30,45,90]
A = 288, k = 32
F = [2,4,8,16,32,64,128,256]
Result: [64,128,256]
If A - k is prime, then there is either one solution (A-k) or none (if A-k <= k).

Set of 3 numbers equal whose sum is equal to T form 3 unsorted arrays ABC [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
We have three arrays A, B and C, unsorted, each array having n numbers. We want to
find a set of three numbers a, b and c where a ϵ A, b ϵ B and c ϵ C, such that Sum of
these numbers is equal to T. (a + b + c = T)
Please solve this for complexity O(n.logn) and O(n.logn2) (TIME COMPLEXITY)
The obvious way is to just brute force.
for(i in a)
for(j in b)
for(k in c)
if(i+j+k == key)
//add triple to the result set
This has a time complexity of O(n3) though. We can do better than that if we sort array c.
sort(c)
for(i in a)
x = key-i
for(j in b)
x -= j
if(c.binary_search(x) != -1) //assuming -1 means element doesn't exist
//add i, j, and x, to the result set
This has a complexity of O(n2.log n)
An even further optimization would be to sort arrays b and c.
sort(c)
sort(b)
for(i in a)
x = key-i
bi = 0
ci = n-1
while(ci >= 0 && bi < n)
if(b[bi]+c[ci] == x)
//add to result set
else if(b[bi]+c[ci] > x)
ci--
else
bi++
This will run in O(n2).
EDIT:
O(n.log n) solution
sort(a)
sort(b)
sort(c)
ai = 0
bi = n-1
while(ai < n && bi >= 0)
x = key-(a[ai]+b[bi])
if(x < c[0])
bi--
else if(x > c[n-1])
ai++
else if(c.binary_search(x) != -1) //assuming -1 means element doesn't exist
//add to result set
EDIT: I realized that this O(n. log n) algorithm is incorrect. It may never halt. I will leave it in the post nevertheless in case someone can suggest a fix for it.
First sort the B and C arrays
B.sort()
C.sort()
Now we will modify a little the 3Sum algorithm to search values from B and C. We will use the same trick but on two different arrays instead of one single array
def Find_Sum(A, B, C, T):
for a in A:
bi = 0
ci = len(C)
while(bi < len(B) and ci >= 0):
b = B[bi]
c = C[ci]
s = a + b + c
if s == T:
return (a, b, c)
elif s > T:
ci -= 1
else:
bi += 1
return False
This algorithm is O(n²).
As specified in the wikipedia page, you can achieve a O(n + nlogn) by computing A+B and comparing it with C. I'll let you do the research for this one.
O(n2) algorithm:
1 - Using merge sort, merge the arrays into a sorted one
2 - Now solve the 3SUM problem with a little moddification
S = Mergesort(A,B,C);
for i=0 to n-3 do
a = S[i];
k = i+1;
l = n-1;
while (k<l) do
b = S[k];
c = S[l];
if (a+b+c == T) then
output a, b, c;
exit;
else if (a+b+c > 0) then
l = l - 1;
else
k = k + 1;
end
end
end
output "not found"//or return whatever you want!
When the integers are in the range [-u, ... , u], 3SUM can be solved in O(n + u.log u) time by representing the input set S as a bit vector, computing the set S+S of all pairwise sums as a discrete convolution using the Fast Fourier transform, and finally comparing this set to -S.

Longest Increasing Sub sequence

Here is the pseudo code for longest increasing sub sequence given on Wikipedia
L = 0
for i = 1, 2, ... n:
binary search for the largest positive j ≤ L
such that X[M[j]] < X[i] (or set j = 0 if no such value exists)
P[i] = M[j]
if j == L or X[i] < X[M[j+1]]:
M[j+1] = i
L = max(L, j+1)
I have understood how the code works. The only thing i cannot understand is the necessity of this statement (if j == L or X[i] < X[M[j+1]]:)
I have tried running the algorithm on many examples and what i could make out is that in all the cases either j == L or X[i] < X[M[j+1]] and so the if statement always evaluates to True. Could you give me an example where the if loop is false and thus required for the algorithm ??
When there are duplicates the if condition will fail
Consider X={2, 2, 2}
if Condition fails when j=0 and L=1

Resources