Reputation: 53
How can I build a function that returns the number of appearances of a given int x in a sorted array, in O(log n) complexity?
static public int count (int [] a, int x);
I'm thinking I might use a binary search to the find the first / last appearance, then continue searching for the last / first appearance, and return the number of instances, but that this is O(log n) complexity .
Upvotes: 3
Views: 523
Reputation: 1799
Here my solution. In a sorted array binarySearch finds the position of a number in log(n) steps. If the number is not present it finds the position that the number should be at, if it were in the array. If you search for x+-1/2 those values will never be in the array, but instead will give you the bounds for x, because it tries to find a value lower/higher than x that cannot exist in an integer array. The comparison automatically converts your ints to double so that everything runs flawlessly.
import java.util.ArrayList;
import java.util.List;
public class SearchCount {
public static void main(String[] args) {
final List<Integer> test = new ArrayList<Integer>();
for(int i = 1; i <= 100; i++) {
for(int j = 0; j < i && i != 50; j++) {
test.add(i);
}
}
final int[] intTest = new int[test.size()];
for (int j = 0; j < test.size(); j++) {
final int i = test.get(j);
intTest[j] = i;
}
for(int x = 0; x <= 101; x++) {
System.out.println(count(intTest,x));
}
}
public static int count (int[] a, int realKey) {
final double lowKey = realKey-0.5;
final double highKey = realKey+0.5;
final int lowerBound = binarySearch(a,0,a.length-1,lowKey);
final int upperBound = binarySearch(a,0,a.length-1,highKey);
return upperBound-lowerBound;
}
public static int binarySearch(int[] data, int low, int high, double key)
{
while(high >= low) {
final int middle = (low + high) / 2;
if(data[middle] < key) {
low = middle + 1;
}
if(key < data[middle]) {
high = middle - 1;
}
}
return high < low?low:high;
}
}
Upvotes: 2
Reputation: 372942
Your idea actually works in time O(log n) if you implement it correctly. Do one binary search to find the index i of the first copy of the element, then do another binary search to find the index j of the last copy of the element, then return j - i + 1. Each binary search takes time O(log n), so the total work done is O(log n) + O(log n) = O(log n).
Upvotes: 3