C# Corner Delhi Chapter "How to Crack the Coding Interview": Discussion of Test

Structs in the C language

Why can't we have a situation as in the following:

  1. struct Node{  
  2.    int data;  
  3.    Node link;  
  4. }; 

Memory allocation of objects of type Node will require infinite memory because of the nested definition. But the same problem will not exist if a link field inside the struct is a Node* (a pointer to a Node, not a Node). Hence the following is allowed.

  1. struct Node{  
  2.    int data;  
  3.    Node* link;  
  4. }; 

This forms the basis of data structures allocated on the heap (linked list and Binary trees).

Programs covered

The following is a function that traverses a linked list in a forward direction:

  1. void printList(Node* head)  
  2. {  
  3.    while(head->link != NULL)  
  4.    {  
  5.       printf("%d", head->data);  
  6.       head = head->link;  
  7.    }  

The following is a recursive version of the preceding code:

  1. void printList(Node* head)  
  2. {  
  3.    if(head == NULL){ return ; }  
  5.    printf("%d", head->data);  
  7.    printList(head->link);  

We said that a recursive function takes more time and more memory than the non-recursive counterpart and hence is never recommended. But in some cases (like implementing a Binary Tree and Graph algorithms) it is very convenient to write recursive algorithms because the problem can be visualized in terms of sub-problems.

For example, consider the problem of printing the list in reverse order. The recursive code is very easy, we just need to change the function from tail recursion to head recursion:

  1. void printList(Node* head)  
  2. {  
  3.    if(head == NULL){ return ; }  
  5.    printList(head->link);  
  7.    printf("%d", head->data);  

But if we want to write a non-recursive function for it then it will be a challenge.

Question: write a non-recursive function that will print the list in reverse order (last node to first node).

Searching in an Array

Given an Array of numbers a0, a1, a2, …. an and a number x. Write a function that will return i, such that:

  1. ai == x 

If x is not in the Array, then return -1 (which means “Not Found”).

Signature of the function

  1. int search(int *arr, int n, int x); 

Linear Search

  • Start the search from the first element and continue until you get the element (or reach end of the array).

    1. /** Function searches data in an array arr of size n. 
    2. * If finds data in arr, then it returns the index of first 
    3. * occurrence of array. 
    4. * Else returns -1 to indicate that data is not found in array. */  
    5. int linearSearch(int * arr, int n , int data){  
    6.    for(int i=0; i<n; i++){  
    7.       if(arr[i] == data)  
    8.       return i;  
    9.    }  
    10.    return -1;  

    Time taken by the function.

  • Best Case: O(1): When the element is found at the first index.

  • Worst Case: O(n): If an element is not found in the array at all.

  • Avg Case: O(n): If found at the first position then 1 comparison, if at the second position then 2 comparisons and so on. If found at the last position then n comparisons.
Linear Search Facts
  • Array may not be sorted.

  • The later we find the element in the array the more time will it take.

  • The performance improves if the value to be searched for is more likely to be near the start of the array than toward its end.

  • If you are ordering the array then place values that are more likely to be searched than others toward the beginning of the array.

  • If the array size is small then use a linear search.

  • When the list items are arranged in order of decreasing probability and these probabilities are geometrically distributed, the cost of the linear search is only O(1), which is faster than for a Binary Search.

  • Can be applied to linked lists or other lists that do not have an index (for example File).

Binary Search Algorithm

  • Array must be sorted.

  • Dichotomic Divide and Conquer Algorithm.

  • Halves the number of elements to be searched with each iteration.

  • If data == Middle element of array.

    • Element found, return the middle index.

  • Else

    • If data < Middle element of array.

      • Repeat the algorithm for the left half of the array.

    • Else

      • Repeat the algorithm for the right half of the array.

  • If there is no remaining array to be searched then not found.
  1. /** Non-Recursive Function */  
  3. int bSearch(int * arr, int n, int data){  
  4.     int l=0, h=n-1, m;  
  6.     while(l <= h){  
  7.         m = (l + h) / 2;  
  9.         if(arr[m] == data)  
  10.             return m;               // FOUND.  
  11.         else if(arr[m] < data)  
  12.             l = m + 1;  
  13.         else  
  14.             h = m – 1;  
  15.     }  
  16.     return -1;                  // NOT FOUND  
  17. }  
  19. /** Recursive Function */  
  21. int bSearch(int * arr, int l , int h, int data){  
  23.     if(l > h || arr[l] > data || arr[h] < data)  
  24.         return -1;          // NOT FOUND.  
  25.     else  
  26.     {  
  27.         int m = (l+h)/2;  
  29.         if(arr[m] == data)  
  30.             return m;       // FOUND.  
  31.         else if (arr[m]<data)  
  32.             return bSearch(arr, m+1, h, data)  
  33.         else  
  34.             return bSearch(arr, l, m-1, data);  
  35.     }  

Time Complexity

    Best case: O( 1 ) Found at the middle of an entire array

    Worst case: O( lg (n) ) not found

    Average case: O( lg (n) )

Space Complexity

    Non-Recursive: O(1)

    Recursive: O( lg(n) )

  • Example of applicability: dictionary, telephone directory.

  • A Binary Search Tree follows a similar methodology. Just that the tree may not be perfectly balanced (In an array, mid actually divides the array in two equal halves).

Questions Discussed

Q1. A sorted array is rotated around a pivot. For example:

  • Input Array
  • Rotated Array

Write code to find the pivot position of the rotation of the array (above: 2).

Q2. Write a function to search in a pivoted array (the pivot is given).

Q3. Given an array of numbers and a number x, write a function to search for two elements in the array, whose sum is x.

Q4. Given an array of integers where each number is repeated an even number of times except for one integer that is repeating an odd number of times. Find that number.

Q5. Given an array of integers of size N-1 where all the integers are unique and are in the range of 1 to N. One integer is missing, write the code to find the missing integer.

Assignment Questions

  1. Write code to search in a matrix sorted by row and by column.

  2. Write code to search for an element in a Binary Search Tree.