Home About My Portfolio Privacy Policy Terms

Sunday, 27 March 2022

The QuickSelect Algorithm

What is QuickSelect Algorithm?


Suppose I give you an array of numbers and ask you to give me the  smallest number. How will you come out with solution?

One simple solution is to sort the array and return the element at   index, or  ARR[K-1]. 

C++ code
int kthSmallest(int *arr,int n,int k)
{
    sort(arr,arr+n);
    return arr[k-1];
}

The time complexity of this approach will be depending upon the sorting algorithm we use. Let us suppose we use the very popular comparison based sorting algorithm known as quicksort. 
Since time complexity of quicksort is  .  Therefore our naive solution will also have the same complexity of  

Is it a good approach?
Surely no because by sorting the whole array, we will be in the position to answer each element from k=1 to k=N ( N is the length of the array). What I want to say is we are doing extra efforts, which we can skip.

Before heading towards our goal, first let us know about the partitioning algorithm.

Partitioning Algorithm

Partitioning algorithm is a subroutine of quicksort algorithm which creates a pivot in the array and returns its index. Elements in the left hand side of the array are less than the pivot and that of right side are greater than the pivot.

for example, if the array is 3,2,1,5,6,4. Then after partitioning it will look like  1,2,3,5,6,4. 

It takes the first element and places it at some index such that all elements before it are lesser than it and all element to its right are greater than it. 
Here 3 is selected as pivot and placed at index 2. 

C++ code
int partition(int *arr,int lb,int ub)
{
    int start=lb,end=ub;
    int pivot=arr[start];
    while(start<end )
    {
        while(arr[start]<=pivot)
        ++start;
        while(arr[end]>pivot)
        --end;
        if(start<end)
        swap(arr[start],arr[end]);
    }
    swap(arr[lb],arr[end]);
    return end;
}
    

Time complexity of this partitioning algorithm is 

QuickSelect Algorithm:

Similar to quicksort algorithm, quickselect calls partition function as it subroutine. The partition function partitions the array into two parts and returns the index of  the pivot element. 

Now, if the index of the pivot element is equal to k, then the quickselect functions returns the pivot, else if k is greater than the pivot index, then the quickselect is called for the right side of the array or if k is less than the pivot index, then the quickseleck is called for the left side of the array.

Look at the code for better understanding.

int quickSelect(int *arr,int start,int end,int k)
{
    if(start>end)
    return 0;

    int pInd=partition(arr,start,end);
    if(pInd==k)
    return arr[pInd];

    if(k>pInd)
    {  
        quickSelect(arr,pInd+1,end,k);
    }
    else
    {  
        quickSelect(arr,start,pInd-1,k);
    }
}


Now let's do the analysis of QuickSelect algorithm:




Tuesday, 15 March 2022

Primality Test

What is Primality test?

Primality test is an algorithm used to determine if a number is prime or not.
One of the basic algorithm used is given below:

Its time complexity is O(√n), and space complexity is O(1).
Suppose n is greater than 10^20 ie out of range of the long long int , the largest container of c++ in terms of size(8 bytes). In this case the mentioned algo will indeed perform poorly. Therefore we must have some techinque/algorithm to counter bigger numbers.



Sieve of Eratosthenes



Why is this algorithm efficient?


One of the best algorithm to check if a number is prime or not is given below:

The time complexity of this algorithm is O(√n), here 'n' is the number under consideration. Suppose we have a total of 'Q' numbers , Q and n can be as large as a million. Now we have to check each number whether it is prime or not.

Since, n and Q are the order of 10^6, therefore in worst case, our machine would have to do O(Q√n) computations ie ~10^6*10^3=10^9 computations, which will take more than the expected time!

Here comes this Sieve algorithm. It is a preprocessing technique which generates all the prime numbers between 0 and a given limit. It is very efficient in cases we have to find all the prime numbers between a range.

Time Complexity O(nlog(n)log(n))
Auxiliary Space O(n)



Implementation of the algorithm using C++