This was asked in on-site Microsoft interview.
Count the number of occurrences of a given key in an array.
I answered linear search because the elements may be s
#include<stdio.h>
int binarysearch(int a[],int n,int k,bool searchfirst){
int result=-1;
int low=0,high=n-1;
while(low<=high){
int mid=(low+high)/2;
if(a[mid]==k) {
result=mid;
if(searchfirst)
high=mid-1;
else
low=mid+1;
}
else if(k<a[mid]) high=mid-1;
else low=mid+1;
}
return result;
}
int main(){
int a[]={1,1,1,2,2,3,3,3,6,6,6,6,6,7,7};
int n=sizeof(a)/sizeof(a[0]);
int x=6;
int firstindex=binarysearch(a,n,x,true);
printf("%d\n",firstindex);
if(firstindex==-1){
printf("elment not found in the array:\n ");
}
else {
int lastindex=binarysearch(a,n,x,false);
printf("%d\n",lastindex);
printf("count is = %d", lastindex-firstindex+1);
}
}
If the array is unsorted, yes, linear search from one end to the other is as good as it gets.
However, if the array is sorted, you can do better than linear time by applying binary or interpolation search techniques.
Treat the problem as the same as "Find the number X in a sorted list" with the added detail of "then scan left and right to determine how many times X appears". The first part, the search, is best done with binary or interpolation search in most cases.
http://en.wikipedia.org/wiki/Interpolation_search
http://en.wikipedia.org/wiki/Binary_search
Yes, you're right for unsorted array, but for sorted array you can use binary search to locate one occurence of the element and once that one occurence is found only scan adjacent elements until you find mismatches and then stop.
For unsorted array there is not much we can do other than linear search.
For sorted array you can do it in O(logN)
using a slightly modified binary search:
key
, call it f
.key
, call it l
.key
exists in the array l-f+1
is the answer.Finding the first occurrence:
arr[i]
is the first occurrence of key
iff
arr[i] == key
and either
i == 0
( it's the first element of
the array) orarr[i-1] != key
(it's not the first
element of the array and element to
it's left is different)You can slightly modify the binary search to find the first occurrence.
In a binary search you terminate the search when you find arr[mid] == key
.
Modify the condition such that you terminate the search when you find the first occurrence instead of any occurrence.
Algorithm:
low = 0
high = arrSize - 1
while low <= high
mid = (low + high) / 2
//if arr[mid] == key // CHANGE
if arr[mid] == key AND ( mid == 0 OR arr[mid-1] != key )
return mid
//else if ( key < arr[mid] ) // CHANGE
else if ( key <= arr[mid] )
high = mid - 1
else
low = mid + 1
end-if
end-while
return -1
Similarly you can find the last occurrence.
** Time Complexity = O ( lg N ) where N is the size of array
** Arguments for binarySearchXXXXX:**
**
package array;
public class BinarySearchQuestion {
public static int binarySearchFirst(int[] array, int k) {
int begin = 0;
int end = array.length-1;
int mid = -1;
while (begin <= end) {
mid = begin + (end - begin) / 2;
if (array[mid] < k) {
begin = mid + 1;
} else {
end = mid - 1;
}
}
//System.out.println("Begin index :: " + begin + " , array[begin] " + array[begin]);
return (begin <= array.length - 1 && begin >= 0 && array[begin] != k) ? -1 : begin;
// return begin;
}
public static int binarySearchLast(int[] array, int k) {
int begin = 0;
int end = array.length - 1;
int mid = -1;
while (begin <= end) {
mid = begin + (end - begin) / 2;
if (array[mid] > k) {
end = mid - 1;
} else {
begin = mid + 1;
}
}
//System.out.println("Last index end :: " + end + " , array[mid] " + array[end]);
return (end <= array.length - 1 && end >= 0 && array[end] != k) ? -1 : end;
//return end;
}
/**
* @param args
*/
public static void main(String[] args) {
// int[] array = { 0, 1,1,1, 2, 3, 4,4,4,5, 5, 5, 5, 5, 5, 5, 5, 5, 5,5,6,6,6,6, 6, 7, 7, 7,
// 7, 8, 9 };
// int[] array = {-1, 0,1, 1,1,2,3};
int[] array = {1,1,1};
int low = binarySearchFirst(array, 1);
int high = binarySearchLast(array, 1);
int total = (high >= low && low != -1 && high != -1) ? ( high - low + 1 ): 0;
System.out.println("Total Frequency " + total);
}
}
How about this for the sorted part, with O(logN) time complexity?
int count(int a[], int k, int l, int h) {
if (l>h) {
return 0;
}
int mid = (l+h)/2;
if (k > a[mid]) {
return count(a, k, mid+1, h);
}
else if (k < a[mid]) {
return count(a, k, l, mid-1);
}
else {
return count(a, k, mid+1, h) + count(a, k, l, mid-1) + 1;
}
}