Question

I am just wondering if this code can be further improved. This is a simple class which takes in a sorted array and a value as parameters and tries to find the number of times this value occurs in the array.

As far as I know the complexity of the code is O(log n + k) [assuming k is the subset of n]. Can this code be improved furter?

public class SearchSortedArray {
// Find number count in an array. Total Complexity = O(log n + k) [assuming k is the subset of n] 
public static int findNumberCountInAnArray(List<Integer> array, Integer findValue) {
    //Search Index
    Integer searchIndex = findIndex(array, findValue, 0);
    //Find Count
    return countArray(array, searchIndex);
}

// Search Index. Complexity = O(log n)
private static Integer findIndex(List<Integer> array, Integer findValue, int offset) {
    if(array.size() == 0) {
        return null;
    }
    if(findValue < array.get(array.size()/2)) {
        return findIndex(array.subList(0, array.size()/2), findValue, 0);
    } else if(findValue > array.get(array.size()/2)) {
        offset = offset + array.size()/2;
        return findIndex(array.subList(array.size()/2, array.size()), findValue,  offset);
    }
    return array.size()/2+offset;           
}

// Find count. Complexity = O(k) [assuming k is the subset of n] 
private static int countArray(List<Integer> array, Integer searchIndex) {
    if(null == searchIndex) {
        return 0;
    }
    Integer searchValue = array.get(searchIndex);
    Integer searchIndexStore = searchIndex;
    int count = 0;
    while(searchIndex < array.size() && searchValue == array.get(searchIndex)) {
        count++;
        searchIndex++;
    }
    searchIndex = searchIndexStore;
    while(searchIndex > 0 && searchValue == array.get(searchIndex-1)) {
        count++;
        searchIndex--;
    }
    return count;
}
}

Here is the main class

// Test main class. 
public class TestMain {
public static void main(String[] args) {
    Integer[] sample1 = {1, 1, 1, 2, 3, 4, 4, 4, 4, 5, 5, 5}; 
    ArrayList<Integer> arraySample1 = new ArrayList<Integer>(Arrays.asList(sample1));
    // Find the number of times 5 is repeated in the array?
    System.out.println(SearchSortedArray.findNumberCountInAnArray(arraySample1, 5));

    Integer[] sample2 = {1, 1, 2, 3, 3, 4, 5, 8, 8, 9, 9, 10, 10, 14, 18};
    ArrayList<Integer> arraySample2 = new ArrayList<Integer>(Arrays.asList(sample2));   
    // Find the number of times 10 is repeated in the array?
    System.out.println(SearchSortedArray.findNumberCountInAnArray(arraySample2, 10));
  }
}

Thanks.

Was it helpful?

Solution

Instead of one binary search, use two:

  1. First find the first occurence of the value findValue. Let's call that index lo. I believe this is what your findIndex function does.
  2. Then find the first occurence of a value that is greater than findValue, or n if no such value exists. Let's call that index hi.

Now the result is hi - lo.

Runtime: O(log n). Note that if the expected value of k is small, i.e. within a small constant factor of log(n), your code might actually be better because linear search is much more cache-efficient than binary search.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top