Reluctant Search
April 3, 2015
It is simple to translate the article’s pseudocode to Scheme:
(define (research x xs i j)
(if (> i j)
-1
(if (= i j)
(if (= x (vector-ref xs i))
i
-1)
(let ((m (quotient (+ i j) 2)))
(if (<= x (vector-ref xs m))
(let ((k (research x xs (+ m 1) j)))
(if (= k -1)
(research x xs i m)
k)))
(let ((k (research x xs i m)))
(if (= k -1)
(research x xs (+ m 1) j)
k)))))))
Here are two examples:
> (research 3 '#(1 2 3 5 6) 0 4)
2
> (research 4 '#(1 2 3 5 6) 0 4)
-1
You can run the program at http://ideone.com/IA1vZc. Happy belated April Fools’ Day!
In Python.
Surely an O(2n) algorithm is also O(n), at least if I understand the definition of big-O correctly. What is more, you can make linear search take 2n time by running it twice, discarding the first result.
@JohnCowan: Your understanding of big-O notation is correct. Read the article for their definition of pessimal. Basically, it’s cheating to do things like run a calculation twice or include a useless loop that takes up time; the algorithm must make progress toward its goal at every step.
My first attempt was slow enough, but did not produce the correct result. This version seems to work better.
public class ReluctantSearch {
public static void main(String[] args) {
int[] input = new int[] {1, 2, 3, 4, 5, 6};
System.out.println(“Position “+research(3, input, 0, input.length-1));
System.out.println(“Position “+research(7, input, 0, input.length-1));
}
private static int research(int x, int[] input, int i, int j) {
if(i > j) return -1;
if(i == j)
if(x == input[i])
return i;
else return -1;
int m = (i+j)/2;
if(x <= input[m]) {
int k = research(x, input, (m+1), j);
if (k==-1) {
return research(x, input, i, m);
} else return k;
} else {
int k = research(x, input, i, m);
if(k==-1) {
return research(x, input, (m+1), j);
} else return k;
}
}
}
To achieve optimal pessimality, I have transformed the algorithm into non-recursive form with an explicit stack (and done what is effectively the obvious tail recursion elimination):