Efficient way to count occurrences of a key in a sorted array

后端 未结 10 1524
粉色の甜心
粉色の甜心 2021-01-30 23:49

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

相关标签:
10条回答
  • 2021-01-31 00:16
    #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);
        }
    
    }
    
    0 讨论(0)
  • 2021-01-31 00:16

    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

    0 讨论(0)
  • 2021-01-31 00:17

    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.

    0 讨论(0)
  • 2021-01-31 00:19

    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:

    • Find the index of first occurrence of key, call it f.
    • Find the index of last occurrence of key, call it l.
    • If the 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) or
      • arr[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.

    0 讨论(0)
  • 2021-01-31 00:19

    ** Time Complexity = O ( lg N ) where N is the size of array

    ** Arguments for binarySearchXXXXX:**

    1. int[] array is a sorted array of length >= 1
    2. int k : key to search

    **

    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);
    }
    
       }
    
    0 讨论(0)
  • 2021-01-31 00:21

    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;
      }
    }
    
    0 讨论(0)
提交回复
热议问题