Continuous Subarray Sum

Given an integer array, find a continuous subarray where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number. (If their are duplicate answer, return the minimum one in lexicographical order)
Example 1:
Input: [-3, 1, 3, -3, 4]
Output: [1, 4]
Example 2:
Input: [0, 1, 0, 1]
Output: [0, 3]
Explanation: The minimum one in lexicographical order.
Method: We will extend kadane's algorithm to solve this problem.
vector continuousSubarraySum(vector &A) {
    int max_sum = A[0], sum = 0, first = 0, last = 0;
    for(int i=0; i < A.size(); i++) {
        if(sum >= 0) {
            sum += A[i];
        } else {
            sum = A[i];
            first = i;
        }
        if(sum > max_sum) {
            max_sum = sum;
            last = i;
        }
    }
    return vector{first, last};
}
Time Complexity: O(n)
 

Given a sorted array and a number x, write a function that counts the occurrences of x in the sorted array

Given a sorted array and a number x, write a function that counts the occurrences of x in the array. Expected time complexity: O(Logn)
For example:
Input arr = {2, 2, 2, 4, 5, 6, 10}, x = 2
Output: 3

Explanation: 2 occurs 3 times
Method 1 (Linear Search): The simplest way is to loop around the array and count the occurence of x. Time Complexity: O(n)

Method 2 (Binary Search): Use Binary search to get index of the first and last occurrence. Let the index of the first occurrence be i and the index of the last occurrence be j. The frequency of x is (j – i + 1).
#include<bits/stdc++.h>
using namespace std;

int countOccurence(int arr[], int x, int n)
{
    /* get the index of first occurrence of x */
    int *low = lower_bound(arr, arr+n, x);

    /* If element is not present, return 0 */
    if (low == (arr + n) || *low != x)
       return 0;

    /* get the index of last occurrence of x.
       we  are only looking in the subarray
       after first occurrence */
    int *high = upper_bound(low, arr+n, x);

    /* return count */
    return high - low;
}

/* driver function */
int main()
{
    int arr[] = {2, 2, 2, 4, 5, 6, 10};
    int x =  2;
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << (" %d occurs %d times ", x, countOccurence(arr, x, n)) << endl;

    return 0;
}
Output:
3
Time Complexity: O(logn)
 

Length of the Longest Consecutive 1s in Binary Representation

Given a number n, find length of the longest consecutive 1s in its binary representation.
For Example:
Input: n = 100
Output: 2

Explanation: Binary representation of 100 = 1100100
Hence, longest consecutive 1s is 2.
Method 1: The naive solution is to convert the number into its binary form and then loop over the bits, and keep track of the number of consecutive set bits, and the maximum that this value is the required answer.

Method 2: The optimized way is based on the concept that if we AND a bit sequence with a shifted version of itself, we’re effectively removing the trailing 1 from every sequence of consecutive 1s.
      11101111   (x)
    & 11011110   (x << 1)
    ----------
      11001110   (x & (x << 1)) 
        ^    ^
        |    |
   trailing 1 removed
So the operation x = (x & (x << 1)) reduces length of every sequence of 1s by one in binary representation of x. If we keep doing this operation in a loop, we end up with x = 0. The number of iterations required to reach 0 is actually length of the longest consecutive sequence of 1s.
#include<bits/stdc++.h>
using namespace std;

int maxConsecutiveOnes(int n)
{
    /* initialize counter */
    int count = 0;

    /* iterate till reached x= 0 */
    while (n!=0)
    {
        /* This operation reduces length
         of every sequence of 1s by one */
        n = (n & (n << 1));

        count++;
    }

    return count;
}

/* driver function */
int main()
{
    cout << maxConsecutiveOnes(100) << endl;
    cout << maxConsecutiveOnes(250) << endl;
    
    return 0;
}
Output:
2
5
Time Complexity: O(number of bits in n)
,  

Check if a Singly Linked List is Palindrome or not

Problem: Given a singly linked list, determine if its a palindrome. Return 1 or 0 denoting if its a palindrome or not, respectively. Can you do it in O(1) extra space?

For example:
Input l1: 1 -> 2 -> 3 -> 2 -> 1 -> null
Output: Yes

Input l2: 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
Output: No
There are various method of doing this problem. We can do this using stack but it will consume O(N) extra space. Our aim is to do in O(1) extra space. Here is the approach:
  1. Get the middle of the linked list 
  2. Reverse the second half of the linked list 
  3. Check if the first half and second half are identical
The most interesting thing is finding the middle element. When number of nodes are even, the first and second half contain exactly half nodes. When there are odd nodes, we don’t want the middle node as part of any of the lists as we are going to compare them for equality.
class LinkedList 
{
    Node head;
 
    /* linked list Node definition */
    class Node 
    {
        char data;
        Node next;
 
        Node(char d) 
        {
            data = d;
            next = null;
        }
    }
 
    /* method to return required result */
    boolean isPalindrome(Node head) 
    {
        /* handling base case */ 
        if(head == null || head.next == null) {
            return true;
        }

        Node slow = head;
        Node fast = head;

        /* Get the middle of the list. Move slow by 1
           and fast by 2, slow will have the middle
           node */
        while(fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        

        Node prev = null;
        Node curr = slow.next;

        /* reversing the second half of list */
        while(curr != null) {
            Node temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }

        /* attach the reversed second half to first half */
        slow.next = prev;

        /* initialize curr to head of fist half and curr to
           head of second half */
        curr = head;
        slow = slow.next;
        while(slow != null) {
            if(curr.data != slow.data) {
                return false;
            }
            slow = slow.next;
            curr = curr.next;
        }
        return true;
    }
 
    /* adding nodes to linked list */
    public void push(char new_data) 
    {
        Node new_node = new Node(new_data);
        new_node.next = head;
        head = new_node;
    }
 
    /* driver function */
    public static void main(String[] args) {
         
        /* Start with the empty list */
        LinkedList llist = new LinkedList();
 
        char str[] = {'1', '2', '3', '2', '1'};
        String string = new String(str);
        for (int i = 0; i< 5 ; i++) {
            llist.push(str[i]);
        }
        if (llist.isPalindrome(llist.head) != false) 
        {
            System.out.println("Is Palindrome");
        }
        else
        {
            System.out.println("Not Palindrome");
        }
    }
}
Output:
Is Palindrome
Time Complexity: O(N)
, , , ,  

Root to leaf path sum equal to a given number

Problem:Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example: Given below is the tree and sum = 62

Output: Yes

5 -> 25 -> 11 -> 19

Method 1: Add all node to a queue and store sum value of each node to another queue. When it is a leaf node, check the stored sum value.

For the tree above, the queue would be: 5 - 9 - 27 - 14 - 11 - 19 - 21. It will check node 14, 19 and 21. This is a typical breadth first search(BFS) problem.
import java.util.*;

/* definetinon for creation of tree */
class Node 
{
    int data;
    Node left, right;
  
    Node(int item) 
    {
        data = item;
        left = right = null;
    }
}

class BinaryTree {

    Node root;

    public boolean hasPathSum(Node root, int sum) {

        /* handling base case */
        if(root == null) 
            return false;
 
        LinkedList<Node> nodes = new LinkedList<Node>();
        LinkedList<Integer> values = new LinkedList<Integer>();
 
        nodes.add(root);
        values.add(root.data);
 
        while(!nodes.isEmpty()) {
            Node curr = nodes.poll();
            int sumValue = values.poll();
 
            /* check if current node is root root and sum is 
               equal to required sum */
            if(curr.left == null && curr.right == null && sumValue==sum) {
                return true;
            }
 
            /* checking for left node */
            if(curr.left != null) {
                nodes.add(curr.left);
                values.add(sumValue + curr.left.data);
            }
 
            /* checking for right node */
            if(curr.right != null) {
                nodes.add(curr.right);
                values.add(sumValue + curr.right.data);
            }
        }
 
        return false;
    }

    /* driver method */
    public static void main(String args[]) 
    {
        int sum = 62;
         
        /* binary tree is
               5
             /   \
            9    27
           /      \
          14      11
                /   \
               19   21
        */
               
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(5);
        tree.root.left = new Node(9);
        tree.root.right = new Node(27);
        tree.root.left.left = new Node(14);
        tree.root.right.right = new Node(11);
        tree.root.right.right.left = new Node(19);
        tree.root.right.right.right = new Node(21);
  
        if (tree.hasPathSum(tree.root, sum))
            System.out.println("There is a root to leaf path with sum " + sum);
        else
            System.out.println("There is no root to leaf path with sum " + sum);
    }
}
Output:
There is a root to leaf path with sum 62
Time Complexity: O(n)

Method 2: We can also do this problem using recursion. Below is the function program for recursion.
public boolean hasPathSum(TreeNode root, int sum) {

    /* handling base case */
    if (root == null)
        return false;

    /* if current node is leaf node */
    if (root.val == sum && (root.left == null && root.right == null))
        return true;
 
    /* recursing for left and right sub-tree */
    return hasPathSum(root.left, sum - root.val)
            || hasPathSum(root.right, sum - root.val);
}
Time Complexity: O(n)
, ,  

Find The First Non Repeated Character In A String

Problem: Given a string, find the first non-repeating character in it.
For example:
Input s = "stress"
Output: t

Input: s = "InterviewDesk"
Output: I
Method 1: We know a non repeated character occurs only once in the string, so if we store the number of times each alphabet appears in the string, it would help us identifying which characters are non repeated characters in the string. Following is the algorithm:
  1. Scan the string from left to right and construct the count array. 
  2. Again, scan the string from left to right and check for count of each character, if you find an element who's count is 1, return it.
import java.util.HashMap;

class practice {
    
    public static int firstNonRepeatedCharacter(String s)
    {
     /* Auxilary array to store the frequency */
     char count[] = new char[256];
        for(int i=0; i < s.length(); i++)
        {
             count[s.charAt(i)]++;
        }

        /* search count in order of string s */
        for (int i = 0; i < s.length(); i++)
        {
            if(count[s.charAt(i)] == 1)
             return i;
        }
        return -1;
    }

    /* driver method */
    public static void main(String[] args)
    {
        String s = "InterviewDesk";
        int ind = firstNonRepeatedCharacter(s);
        System.out.println(ind == -1 ? "All characters repeating" : "The first non repeated character is :  " + s.charAt(ind));
    }
}
Output:
The first non repeated character is :  I
Time Complexity: O(2*n)
,  

Number of buildings facing the Sun

Problem: The heights of the building is given in an array. Buildings are facing the sun. You have to tell which all buildings will see the sunset. It is assumed that heights of all buildings are distinct.
For example:
Input : arr[] = {7, 4, 8, 2, 9}
Output: 3

4 can't see the sunset as 7 is hiding it. 
8 can see.
2 can't see the sunset.
9 also can see the sunset.
Method 1: Seeing the above picture we can say that only the maximum element found so far will see the sunlight i.e. curr_max will see the sunlight and then only the element greater than curr_max will see the sunlight. The algorithm is:
  1. Traverse given array from left to right.
  2. Keep track of maximum element seen so far
  3. Whenever an element becomes more than current max, increment result and update current max.
class InterviewDesk
{
    /* method to return count of buildings that 
       can see the sunlight */
    static int buildingCount(int height[], int n)
    {
        /* initial the result. The first building will
           always see the sunlight */
        int count = 1;
      
        int curr_max = height[0];
        for (int i=1; i curr_max)
            {
                count++;
                curr_max=height[i];
            }
        }
      
        /* return the result */
        return count;
    }
     
    // Driver method
    public static void main(String[] args) 
    {
        int height[] = {7, 4, 8, 2, 9};
         
        System.out.println(buildingCount(height, height.length));
    }
}
Output:
3
Time Complexity: O(n)
,  

Check if a linked list is Circular Linked List

Problem: Given a singly linked list, find if the linked list is circular or not.


Circular Linked List: A linked list is called circular if it not NULL terminated and all nodes are connected in the form of a cycle.

For example:

Input:
Output: Yes

Input:
Output: No

Method 1: Maintain two pointers, fast and slow is used while iterating over linked list. Fast pointer moves two nodes in each iteration, while slow pointer moves to one node. If linked list contains loop or cycle than both fast and slow pointer will meet at some point during iteration. If they don't meet and fast or slow will point to null, then linked list is not cyclic and it doesn't contain any loop.

Below is the exact algorithm:
  1. Use two pointers fast and slow 
  2. Move fast two nodes and slow one node in each iteration 
  3. If fast and slow meet then linked list contains cycle 
  4. if fast points to null or fast.next points to null then linked list is not cyclic
This algorithm is also known as Floyd’s cycle finding algorithm and popularly known as tortoise and hare algorithm to find cycles in linked list.
bool findCircular(Node *head)
{ 
    /* initial two pointers */
    Node fast = head; 
    Node slow = head;

    while(fast != null && fast.next != null)
    {
        /* advance fast pointer twice as slow pointer */
        fast = fast.next.next; 
        slow = slow.next; 
        if(fast == slow )
        { 
            return true; 
        } 
    } 
    return false; 
}
Time Complexity: O(n)
, ,  

Reverse every K nodes of a Linked List

Problem: Given a linked list and a positive number K, reverse every K nodes in the list.

For example:
Input L1: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> NULL
      K = 3
Output: 3 -> 2 -> 1 -> 6 -> 5 -> 4 -> 8 -> 7 -> NULL

Input L2: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> NULL 
      K = 2
Output 2 -> 1 -> 4 -> 3 -> 6 -> 5 -> NULL
Method 1: Recursive Method
  1. Reverse the first sub-list of size k. 
  2. While reversing keep track of the next node and previous node. Let the pointer to the next node be next and pointer to the previous node be prev.
  3. Now next points to (k+1)th node
  4. head->next = reverse(next, k), Recursively call for rest of the list and link the two sub-lists
  5. return prev, prev becomes the new head of the list
Node reverseKNodes(Node *head, int k)
{
    Node curr = head;
    Node next = null;
    Node prev = null;
    
    int count = 0;

    /* Reverse first k nodes of linked list */
    while (count < k && curr != null) 
    {
        next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
        count++;
    }

    /* next is now a pointer to (k+1)th node 
       Recursively call for the list starting from current.
       And make rest of the list as next of first node */
    if (next != null) 
        head.next = reverseKNodes(next, k);

    /* prev is now head of input list */
    return prev;
}   
Time Complexity: O(n)
, ,  

Merge two sorted arrays

Problem: Given two sorted arrays, the task is to merge them in a sorted manner.

For example:
Input  : arr1[] = { 5, 8, 9}  
         arr2[] = {4, 7, 8}
Output : arr3[] = {4, 5, 7, 8, 8, 9}
As the task is of merging two arrays, we use the idea of Merge Sort.
  1. Create an array aux[] of size len1 + len2. 
  2. Simultaneously traverse arr1[] and arr2[]. 
    1. Pick smaller of current elements in arr1[] and arr2[], copy this smaller element to next position in aux[] and move ahead in aux[] and the array whose element is picked.
  3. If there are are remaining elements in arr1[] or arr2[], copy them also in aux[].
import java.util.*;
import java.lang.*;
import java.io.*;
 
class InterviewDesk
{
    /* method to merge two sorted arrays */
    public static void mergeTwoArray(int[] arr1, int[] arr2, int len1, int len2, int[] aux)
    {
        /* iterators of 3 arrays */
        int i = 0, j = 0, k = 0;
     
        /* traversing both arrays */
        while (i < len1 && j <len2)
        {
            /* Check if current element of first array is smaller
               than current element of second array. If yes, store 
               first array element and increment first array index.
               Otherwise do same with second array */
            if (arr1[i] < arr2[j])
                aux[k++] = arr1[i++];
            else
                aux[k++] = arr2[j++];
        }
     
        /* store remaining elements of first array */
        while (i < len1)
            aux[k++] = arr1[i++];
     
        /* store remaining elements of second array */
        while (j < len2)
            aux[k++] = arr2[j++];
    }
     
    public static void main (String[] args) 
    {
        int[] arr1 = {1, 3, 5, 7};
        int len1 = arr1.length;
     
        int[] arr2 = {2, 4, 6, 8};
        int len2 = arr2.length;
     
        int[] aux = new int[len1+len2];
         
        mergeTwoArray(arr1, arr2, len1, len2, aux);
     
        for (int i=0; i < len1+len2; i++)
            System.out.print(aux[i] + " ");
    }
}
Output:
1 2 3 4 5 6 7 8
Time Complexity: O(len1 + len2) and Auxiliary Space: O(len1 + len2)
,  

Find Nth Fibbonacci Number

Problem: Find Nth fibonacci number in O(logN) time complexity.
Fibonacci Series: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
F(n) = F(n-1) + F(n-2)

with initial values: F(0) = 0 and F(1) = 1
For example:
Input: n = 9
Output: 34
Method 1: A simple method that is a direct recursive implementation mathematical recurrence relation given above.
class InterviewDesk
{
    /* method to return required result */
    static int fibonacci(int n)
    {
        /* handling base condition */
        if (n <= 1)
            return n;
        return 
            fibonacci(n-1) + fibonacci(n-2);
    }
     
    /* driver method */
    public static void main (String args[])
    {
        int n = 9;
        System.out.println(fibonacci(n));
    }
}
Output:
34
Time Complexity: Exponential

Method 2: As in above algorithm, we are processing for same sub-problem many times. Hence we follow dynamic approach to avoid calculation of same sub-problem again and again.
class InterviewDesk
{
    /* method to return required result */
    static int Fibonacci(int n)
    {
        int a = 0, b = 1, c;
        
        /* handling base case */
        if (n == 0)
            return a;

        for (int i = 2; i <= n; i++)
        {
            c = a + b;
            a = b;
            b = c;
        }
        
        return b;
    }

    /* driver method */
    public static void main (String args[])
    {
        int n = 9;
        System.out.println(Fibonacci(n));
    }
}
Output:
34
Time Complexity: O(n) and Space Complexity: O(1)

Method 3: Most optimized solution:
We all know the Fibonacci recurrence as F(n+1) = F(n) + F(n-1) but we can represent this in the form a matrix as shown below:


Look at the matrix A = [ [ 1 1 ] [ 1 0 ] ] . Multiplying A with [ F(n) F(n-1) ] gives us [ F(n+1) F(n) ] , so we say that

A* [ F(n) F(n-1) ] = [ F(n+1) F(n) ]

start with [ F(1) F(0) ] , multiplying it with A gives us [ F(2) F(1) ]; again multiplying [ F(2) F(1) ] with A gives us [ F(3) F(2) ] and so on ...
A* [ F(1) F(0) ] = [ F(2) F(1) ]
A* [ F(2) F(1) ] = [ F(3) F(2) ] = A^2 * [ F(1) F(0) ]
A* [ F(3) F(2) ] = [ F(4) F(3) ] = A^3 * [ F(1) F(0) ]
.
.
.
.
A* [ F(n) F(n-1) ] = [ F(n+1) F(n) ] = A^n * [ F(1) F(0) ]
So all that is left is finding the nth power of the matrix A. Well, this can be computed in O(log n) time, by recursive doubling. The idea is, to find A^n , we can do R = A^(n/2) * A^(n/2) and if n is odd, we need do multiply with an A at the end.

Following is the code:
class InterviewDesk
{
    /* method to return required result */
    static int fib(int n)
    {
        int F[][] = new int[][]{{1,1},{1,0}};
        if (n == 0)
            return 0;
        power(F, n-1);
        
        return F[0][0];
    }
     
    /* method to multiply 2 matrices F and M of size 2*2, and
     puts the multiplication result back to F[][] */
    static void multiply(int F[][], int M[][])
    {
        int x =  F[0][0]*M[0][0] + F[0][1]*M[1][0];
        int y =  F[0][0]*M[0][1] + F[0][1]*M[1][1];
        int z =  F[1][0]*M[0][0] + F[1][1]*M[1][0];
        int w =  F[1][0]*M[0][1] + F[1][1]*M[1][1];
         
        F[0][0] = x;
        F[0][1] = y;
        F[1][0] = z;
        F[1][1] = w;
    }

    /* method that calculates F[][] raise to the power n and puts the
    result in F[][] */
    static void power(int F[][], int n)
    {
        int i;
        int M[][] = new int[][]{{1,1},{1,0}};
        
        /* n - 1 times multiply the matrix to {{1,0},{0,1}} */
        for (i = 2; i <= n; i++)
            multiply(F, M);
    }
     
    /* driver method */
    public static void main (String args[])
    {
        int n = 9;
        System.out.println(fib(n));
    }
}
Output:
34
Time Complexity: O(logn)
,  

Minimum number of squares whose sum equals to given number N

Problem: Given number N, find the least number of perfect square number sum needed to get N.

For example:
Input: n = 20
Output: 2

20 = (16 + 4) i.e 2

Input: n = 12
Output: 3

12 = (9 + 1 + 1 + 1) i.e 3
This question can be solved with the basic knowledge of recursion.

Idea is to take a list of perfect square numbers i.e. 1, 4, 9, 16, 25,… and see from which number a minimum jump can be performed. We only need to check till sqrt(N) numbers in above list, since from sqrt(N)th number we can directly jump on N.

Let proceed with an example:

let N=12 , thus we need to traverse only sqrt(12) = 3 numbers i.e. {1, 4, 9} since from 16 onward we can’t reach 12. This thing clearly explains sqrt(N) concept.

Now, to reach 12 we have 3 choices,
  1. from (12-1)th state. 11th 
  2. from (12-4)th state. 8th 
  3. from (12-9)th state. 3rd 
 So, we just take (minimum cost to reach 11th, 8th, 3rd) + 1 as the answer to reach 12th state.

Method 1: One of the method is to use recursion. Following is the implementation:
class practice 
{

    /* method to return required result */
    public static int minNumbers(int n, int sq) 
    {
        
        /* handling base case */
        if (n <= 0) 
        {
            return 0;
        }

        int min = minNumbers(n - 1 * 1, sq);

        /* checking for all numbers from 2 to sqrt(n) */
        for (int i = 2; i <= sq; i++) 
        {
            if (n >= i * i) 
            {
                min = Math.min(min, minNumbers(n - i * i, sq));
            }
        }
        
        return min + 1;
    }

    /* driver method */
    public static void main(String[] args) 
    {
        
        int n = 20;
        int sq = (int) Math.sqrt(n);
        System.out.println(minNumbers(n, sq));

    }
}
Output:
2
Time Complexity: Exponential

Method 2: We need more optimised solution. If we draw the complete recursion tree, we can observer that many sub-problems are solved again and again. For example, when we start from n = 6, we can reach 4 by subtracting one 2 times and by subtracting 2 one times. So the subproblem for 4 is called twice.

Hence we follow a dynamic approach to solve this problem. Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided by constructing a temporary array table[][] in bottom up manner.

Below is Dynamic Programming based solution:
class practice
{
    /* method to return required result */
    static int minNumbers(int n)
    {
        /* dynamic programming table to store sq */
        int dp[] = new int[n+1];
      
        /* table for base case entries */
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
      
        /* filling rest of the table using recursive formula */
        for (int i = 4; i <= n; i++)
        {
            /* max value is i as i can always be represented
               as 1*1 + 1*1 + ... */
            dp[i] = i;
      
            /* go through all smaller numbers to recursively find minimum */
            for (int x = 1; x <= i; x++) {
                int temp = x*x;
                if (temp > i)
                    break;
                else 
                    dp[i] = Math.min(dp[i], 1 + dp[i-temp]);
            }
        }
      
        return dp[n];
    }

    /* driver method */
    public static void main(String args[])
    {
       System.out.println(minNumbers(20));
    }
}
Output:
2
Time Complexity: N*sqrt(N)
,  

Find maximum of minimum for every window size in a given array

Problem: Given an integer array of size n, find the maximum of the minimum’s of every window size in the array.

For example:
Input: arr[] = {10, 20, 30, 50, 10, 70, 30}
Output: 7 3 2 1 1 1 1

First element in output indicates maximum of minimums of all 
windows of size 1.
Minimums of windows of size 1 are {1}, {2}, {3}, {5}, {1},
{7} and {3}. Maximum of these minimums is 7

Second element in output indicates maximum of minimums of all 
windows of size 2.
Minimums of windows of size 2 are {1}, {2}, {3}, {1}, {1},
and {3}.  Maximum of these minimums is 3

Third element in output indicates maximum of minimums of all 
windows of size 3.
Minimums of windows of size 3 are {1}, {2}, {1}, {1} and {1}. 
Maximum of these minimums is 2

Similarly other elements of output are computed.
Method 1: The brute-force is to consider sub-array of all size and then find the maximum of all sub-arrays.
class practice
{   
    /* method to print the required result */  
    static void printMaxOfMin(int arr[], int n)
    {
        /* Consider all windows of different sizes starting
           from size 1 */
        for (int k=1; k<=n; k++)
        {
            /* initialize max of min for current window size k */
            int maxOfMin = arr[0];
      
            /* traverse through all windows of current size k */
            for (int i = 0; i <= n-k; i++)
            {
                /* Finding minimum of current window */
                int min = arr[i];
                for (int j = 1; j < k; j++)
                {
                    if (arr[i+j] < min)
                        min = arr[i+j];
                }
      
                /* Update maxOfMin if required */
                if (min > maxOfMin)
                  maxOfMin = min;
            }
      
            /* Print max of min for current window size */
            System.out.print(maxOfMin + " ");
        }
    }
     
    /* driver method */
    public static void main(String[] args) 
    {
        int arr[]  = {1, 2, 3, 5, 1, 7, 3};
        printMaxOfMin(arr, arr.length);
    }
}
Output:
7 3 2 1 1 1 1
Time Complexity: O(n3) and Space Complexity: O(1)

Method 2: If we work bit hard, we can come out with O(n) algorithm. The idea is to use auxiliary for pre-proccessing.

1. Find indexes of next smaller and previous smaller for every element.

Next smaller: is the nearest smallest element on right side of arr[i]. 
Similarly, Previous smaller: is the nearest smallest element on left side of arr[i]. 
If there is no smaller element on right side, then next smaller is n.If there is no smaller on left side, then previous smaller is -1. 

For input {10, 20, 30, 50, 10, 70, 30}, array of indexes of next smaller is {7, 4, 4, 4, 7, 6, 7} and array of indexes of previous smaller is {-1, 0, 1, 2, -1, 4, 4}. 
This step can be done in O(n). Refer this post.

2. Once we have indexes of next and previous smaller, we know that arr[i] is a minimum of a window of length “right[i] – left[i] – 1”. Lengths of windows for which the elements are minimum are {7, 3, 2, 1, 7, 1, 2}. This array indicates, first element is minimum in window of size 7, second element is minimum in window of size 3, and so on. 

Create an auxiliary array ans[n+1] to store the result. Values in ans[] can be filled by iterating through right[] and left[]
    for (int i=0; i < n; i++)
    {
        // length of the interval
        int len = right[i] - left[i] - 1;

        // a[i] is the possible answer for
        // this length len interval
        ans[len] = max(ans[len], arr[i]);
    }
We get the ans[] array as {0, 70, 30, 20, 0, 0, 0, 10}. Note that ans[0] or answer for length 0 is useless. 

3. Some entries in ans[] are 0 and yet to be filled. For example, we know maximum of minimum for lengths 1, 2, 3 and 7 are 70, 30, 20 and 10 respectively, but we don’t know the same for lengths 4, 5 and 6. 

Below are few important observations to fill remaining entries 
a) Result for length i, i.e. ans[i] would always be greater or same as result for length i+1, i.e., ans[i+1].
b) If ans[i] is not filled it means there is no direct element which is minimum of length i and therefore either the element of length ans[i+1], or ans[i+2], and so on is same as ans[i] 

So we fill rest of the entries using below loop.
    for (int i=n-1; i>=1; i--)
        ans[i] = max(ans[i], ans[i+1]);
Below is implementation of above algorithm.
import java.util.Stack;
 
class practice
{    
    /* method to print the required result */
    static void printMaxOfMin(int arr[], int n)
    {
        /* used to find previous and next smaller */
        Stack s = new Stack<>();
      
        /* Arrays to store previous and next smaller */
        int left[] = new int[n+1];  
        int right[]  = new int[n+1]; 
      
        /* Initialize elements of left[] and right[] */
        for (int i=0; i= arr[i])
                s.pop();
      
            if (!s.empty())
                left[i] = s.peek();
      
            s.push(i);
        }
      
        /* use same stack for right[] */
        while (!s.empty())
            s.pop();
      
        /* filling the right[] array */
        for (int i = n-1 ; i>=0 ; i-- )
        {
            while (!s.empty() && arr[s.peek()] >= arr[i])
                s.pop();
      
            if(!s.empty())
                right[i] = s.peek();
      
            s.push(i);
        }
      
        /* initial answer array */
        int ans[] = new int[n+1];
        for (int i=0; i<=n; i++)
            ans[i] = 0;
      
        /* Fill answer array by comparing minimums of all
           lengths computed using left[] and right[] */
        for (int i=0; i=1; i--)
            ans[i] = Math.max(ans[i], ans[i+1]);
      
        /* printing result */
        for (int i=1; i<=n; i++)
            System.out.print(ans[i] + " ");
    }
     
    /* driver function */
    public static void main(String[] args) 
    {
        int arr[] = {1, 2, 3, 5, 1, 7, 3};
        printMaxOfMin(arr, arr.length);
    }
}
Output:
7 3 2 1 1 1 1
Time Complexity: O(n) and Space Complexity: O(2*n)
, ,  

Spiral Order Traversal of Binary Tree

Problem: Given a binary tree, print its nodes level by level in spiral order.

For example:
The spiral order traversal of the tree above is (1, 3, 2, 4, 5, 6, 7) or (1, 2, 3, 7, 6, 5, 4)

Method 1: The idea is to use two stacks. We can use one stack for printing from left to right and other stack for printing from right to left. In every iteration, we have nodes of one level in one of the stacks. We print the nodes, and push nodes of next level in other stack.
import java.util.*;
 
/* creating Tree node */
class Node 
{
    int data;
    Node left, right;
 
    public Node(int val) 
    {
        data = val;
        left = right = null;
    }
}
 
class BinaryTree 
{
 
    static Node root;
 
    /* function to print spiral of binary tree */
    void printSpiral(Node node) 
    {
        /* checking base case */
        if (node == null) 
            return;
 
        /* two stacks to store alternate levels
           stack s1 used to print nodes from right to left 
           and s2 used to print nodes from left to right */
        Stack s1 = new Stack();
        Stack s2 = new Stack();
 
        /* Push first level to first stack 's1' */
        s1.push(node);
 
        /* Keep ptinting while any of the stacks has some nodes */
        while (!s1.empty() || !s2.empty()) 
        {
            /* Print nodes of current level from s1 and push 
               nodes of next level to s2 */
            while (!s1.empty()) 
            {
                Node temp = s1.peek();
                s1.pop();
                System.out.print(temp.data + " ");
 
                /* Note that is right is pushed before left */
                if (temp.right != null) 
                    s2.push(temp.right);
                 
                if (temp.left != null) 
                    s2.push(temp.left);
                 
            }
 
            /* Print nodes of current level from s2 and push 
               nodes of next level to s1 */
            while (!s2.empty()) 
            {
                Node temp = s2.peek();
                s2.pop();
                System.out.print(temp.data + " ");
 
                /* Note that is left is pushed before right */
                if (temp.left != null)
                    s1.push(temp.left);
                if (temp.right != null)
                    s1.push(temp.right);
            }
        }
    }
 
    public static void main(String[] args) 
    {
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        tree.root.right.left = new Node(6);
        tree.root.right.right = new Node(7);
        tree.printSpiral(root);
    }
}
Output:
1 2 3 7 6 5 4
Method 2: We can also do this problem using Dequeue.
/* function to print spiral of binary tree */
public static void printSpiral(Node root) 
{
    Node temp = root;
    Deque deque = new java.util.LinkedList();
    deque.addLast(temp);
    
    /* boolean varible which store detail of style of printing
       i.e left to right or right to let */
    boolean isReverseLevel = true;

    while (!deque.isEmpty()) 
    {
        int size = deque.size();

        while (size > 0) 
        {
            if (isReverseLevel) 
            {
                Node pollLast = deque.pollLast();
                System.out.print(" " + pollLast.data);
                if (pollLast.right != null) 
                {
                    deque.addFirst(pollLast.right);
                }
                if (pollLast.left != null) 
                {
                    deque.addFirst(pollLast.left);
                }
            } 
            else 
            {
                Node pollFirst = deque.pollFirst();
                System.out.print(" " + pollFirst.data);
                if (pollFirst.left != null) 
                {
                    deque.addLast(pollFirst.left);
                }
                if (pollFirst.right != null) 
                {
                    deque.addLast(pollFirst.right);
                }
            }
            size--;
        }
        isReverseLevel = !isReverseLevel;
    }
}
Time Complexity: O(n) and Space Complexity: O(n)
,  

Count triplets with sum smaller than a given value

Problem: Given an array of distinct integers and a sum value. Find count of triplets with sum smaller than given sum value.

For example:
Input arr[] = {5, 2, 7, 8, 4, 3}
        Sum = 14
Output: 7

There are 7 triplets with sum smaller than given sum value (5, 2, 4), (5, 2, 3), (5, 4, 3), (2, 7, 4), (2, 7, 3), (2, 8, 3), (2, 4, 3)
Method 1: The brute-force solution is to run three loops to consider all triplets one by one. For every triplet, compare the sums and increment count if triplet sum is smaller than given sum.
class InterviewDesk
{    
    static int countTriplets(int arr[], int n, int sum)
    {
        /* initialize result */
        int ans = 0;
      
        /* fix the first element as arr[i] */
        for (int i = 0; i < n-2; i++)
        {
            /* fix the second element as arr[j] */
            for (int j = i+1; j < n-1; j++)
            {
               /* now look for the third number */
                for (int k = j+1; k < n; k++)
                if (arr[i] + arr[j] + arr[k] < sum)
                {
                    ans++;
                }
            }
        }
      
        return ans;
    }
     
    /* driver function */
    public static void main(String[] args) 
    {
        int arr[] = {5, 2, 7, 8, 4, 3};
        int sum = 14; 
        System.out.println(countTriplets(arr, arr.length, sum));
    }
}
Output:
7
Time Complexity: O(n3)

Method 2: We can do this problem in O(n2) by help of following approach:
  1. Sort the input array in increasing order.
  2. Initialize result as 0.
  3. Run a loop from i = 0 to n-2. An iteration of this loop finds all triplets with arr[i] as first element.
    • Initialize other two elements as corner elements of subarray arr[i+1..n-1], i.e. j = i+1 and k = n-1
    • Move j and k toward each other until they meet, i.e. while (j < k)
      •  if (arr[i] + arr[j] + arr[k] >= sum), 
        • then do k-- 
      •  Else Do ans += (k - j) followed by j++
import java.util.Arrays;

class InterviewDesk
{
     
    static int countTriplets(int arr[], int n, int sum)
    {
        /* sort input array */
        Arrays.sort(arr);
      
        /* initialize result */
        int ans = 0;
      
        for (int i = 0; i < n - 2; i++)
        {
            /* Initialize other two elements as corner elements
               of subarray arr[j+1..k] */
            int j = i + 1, k = n - 1;
      
            /* move j and k toward each other until they meet */
            while (j < k)
            {
                /* If sum of current triplet is more or equal,
                   move right corner to look for smaller values */
                if (arr[i] + arr[j] + arr[k] >= sum)
                    k--;
      
                /* else move left corner */
                else
                {
                    /* for current i and j, there can be total k-j 
                       third elements */
                    ans += (k - j);
                    j++;
                }
            }
        }
        return ans;
    }
     
    /* driver function */
    public static void main(String[] args) 
    {
        int arr[] = {5, 2, 7, 8, 4, 3};
        int sum = 14; 
        System.out.println(countTriplets(arr, arr.length, sum));
    }
}
Output:
7
Time Complexity: O(n2)
,  

Find Nth Magic Number

Problem: Given a number n, find out the nth Magic Number.

Magic Numbers: A magic number is defined as a number which can be expressed as a power of 5 or sum of unique powers of 5. First few magic numbers are 5, 25, 30(5 + 25), 125, 130(125 + 5), ...

For example:
Input: n = 25
Output: 3755

Input: n = 30
Output: 3900
Analysing the numbers, we observe that magic numbers can be represented as 001, 010, 011, 100, 101, 110 etc, where 001 is 0*pow(5,3) + 0*pow(5,2) + 1*pow(5,1). So basically we need to add powers of 5 for each bit set in given integer n.
public class MagicNumber {

    /* function returning nth Magic Number */
    public static int NthMagicNum(int n) {
        
        int pow = 1, ans = 0;
        
        /* traversing every bit of n */
        while (n > 0)
        {
           pow = pow*5;
     
           /* If last bit of n is set */
           if ((n & 1) == 1)
             ans += pow;
     
           /* proceed to next bit */
           n >>= 1;
        }
        return ans;
    }
    
    public static void main(String[] args) {
        int n = 120;
        System.out.println(NthMagicNum(n));
    }
}
Output:
97500
, ,  

Two numbers with sum closest to zero

Problem: Given an integer array, you need to find the two elements such that their sum is closest to zero.

For example:
Input: arr[] =  {-21, -67, -37, -18, 4, -65}
Output:-18 4

-18 + 4 = -12 is the closet sum pair to zero.
Method 1: Find the sum of every pair of numbers in the array. Finally, return the minimum sum.
class InterviewDesk
{
  static void minSumPair(int arr[], int len)
  {    
    /* handling base case i.e array should have 
       at least two elements*/
    if(len < 2)
    {
      System.out.println("Invalid Input");
      return;
    }
    
    /* Initialize the values */
    int pos1 = 0, pos2 = 1, min_sum, sum;
    min_sum = arr[pos1] + arr[pos2];
    
    /* calculating for each pair of numbers */
    for(int i = 0; i < len - 1; i++)
    {
      for(int j = i + 1; j < len; j++)
      {
        sum = arr[i] + arr[j];
        if(Math.abs(min_sum) > Math.abs(sum))
        {
          min_sum = sum;
          pos1 = i;
          pos2 = j;
        }
      }
    }
    
    System.out.println(arr[pos1]+ " and "+arr[pos2]);
  }
   
  /* driver function */
  public static void main (String[] args) 
  {
      int arr[] = {1, 60, -10, 70, -80, 85};
      minSumPair(arr, 6);
  }
     
}
Output:
-80 and 85
Time Complexity: O(n2)

Method 2: Below is the algorithm to decrease the time complexity:
  1. Sort the array in non-decreasing order. 
  2. Initialize two index variables to find the candidate elements in the sorted array.
    • Initialize first to the leftmost index: l = 0
    • Initialize second the rightmost index: r = len - 1
  3. Loop while l < r. 
    • sum = Arr[l] + Arr[r]
    • if sum is -ve l++
    • else r--
  4. Keep track of abs min sum
import java.util.Arrays;

class Main
{
  static void minSumPair(int arr[], int len)
  {
    /* keeping track of current sum and minimum sum */
    int sum, min_sum = 999999;
    
    /* left and right index variables */
    int l = 0, r = len - 1;
    
    /* variables to keep track of position of pair with min sum */
    int pos1 = l, pos2 = len - 1;
    
    /* handling base case i.e array should have 
       at least two elements*/
    if(len < 2)
    {
      System.out.println("Invalid Input");
      return;
    }
   
    /* sort the elements */
    Arrays.sort(arr);
    
    while(l < r)
    {
      sum = arr[l] + arr[r];
    
      /*If abs(sum) is less then update the result items*/
      if(Math.abs(sum) < Math.abs(min_sum))
      {
        min_sum = sum;
        pos1 = l;
        pos2 = r;
      }
      if(sum < 0)
        l++;
      else
        r--;
    }
    System.out.println(arr[pos1] + " and " + arr[pos2]);
  }
    
  /* driver function */
  public static void main (String[] args) 
  {
      int arr[] = {1, 60, -10, 70, -80, 85};
      int len = arr.length;
      minSumPair(arr, len);
  }
}
Output:
-80 and 85
Time Complexity: O(n)
,  

Count all numbers with unique digits (in decimal) in the range [1, N]

Problem: Given a range, print all numbers having unique digits.

For example:
Input : 10 20
Output : 10 12 13 14 15 16 17 18 19 20

11 does not has both digits unique.

Input : 1 10
Output : 1 2 3 4 5 6 7 8 9 10
Method 1: A simple approach one can come along is looping from 1 to N and checking each digits if it meets the required constraints i.e:
  1. Find the digits one by one and keep marking visited digits. 
  2. If all digits occurs one time only then print that number. 
  3. Else ignore it
class InterviewDesk
{
  /* method to print numbers with unique digits */
  static void printUnique(int n)
  {
      /* traversing all numbers */
      for (int i = 1; i <= n; i++)
      {
          int num = i;
          boolean visited[] = new boolean[10];
    
          /* find digit and maintain its count */
          while(num > 0)
          {
              /* if a digit occcurs more than 1 time, break */
              if (visited[num % 10])
                  break;
              
              /* mark digit as visited */
              visited[num%10] = true;
    
              num = num/10;
          }
    
          /* print if number has unique digits */
          if (num == 0)
              System.out.print(i + " ");
      }
  }
     
  /* driver method */
  public static void main(String args[])
  {
      int n = 20;
      printUnique(n);
  }
}
Output:
1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20
,  

Count number of occurrences in a sorted array

Problem: Given a sorted array and a number x, write a program that counts the occurrences of x in the given array. Can you do in less than O(n)?

For example:
Input: arr[] = {1,2,2,2,2,2,2,2,3,4,5,5,6}
           x = 2
Output: 7

Input: arr[] = {1, 1, 2, 2, 2, 2, 3,}
           x = 4
Output: -1
4 doesn't occur in arr[]
Method 1: The simplest method is to use linear search and count the frequency of the element x.
/* function to return freq of x */
public static int freqOfx(int[] arr, int len, int x)
{
    /* initialize count */
    int count = 0;

    /* calculating the freq of x */
    for (int i = 0; i > len; i++)
    {
        /* update count when x is found */
        if (arr[i] == x)
        {
            count++;
        }
    }

    /* return count of x */
    return count;
}
Time Complexity: O(n) and Space Complexity: O(1)

Method 2: We can further decrease the complexity of this problem to O(logn) using binary search. Following is the approach:
  1. Use Binary search to get index of the first occurrence of x in arr[]. Let the index of the first occurrence be i. 
  2. Use Binary search to get index of the last occurrence of x in arr[]. Let the index of the last occurrence be j. 
  3. Finally return (j – i + 1)
public class InterviewDesk {
    public int freqOfx(int [] arr, int x)
    {
        /* initialize count */
        int count = 0;

        /* position of first occurence of x */
        int startPoint = firstOccurPos(arr,x,0,arr.length-1);
        
        /* if x is not found */
        if(startPoint < 0)
        {
            return -1;
        }

        /* position of last occurence of x */
        int endPoint = lastOccurPos(arr, x, 0, arr.length-1);
        
        /* calculating total frequency */
        count = endPoint-startPoint+1;
        
        /* return ans */
        return count;
    }

    /* function to return first occurence of x */
    public int firstOccurPos(int[] arr, int x,int start, int end )
    {
        if(end>=start)
        {
            int mid = (start + end) / 2;
            if((mid == 0||(arr[mid-1] < x)) && arr[mid] == x)
            {
                return mid;
            }
            else if(arr[mid]<x)
            {
                return firstOccurPos(arr, x, mid+1, end);
            }
            else
            {
                return firstOccurPos(arr, x, start, mid-1);
            }
        }
        else 
            return -1;
    }

    /* function to return last occurence of x */
    public int lastOccurPos(int [] arr, int x,int start, int end ){
        if(end>=start)
        {
            int mid = (start + end) / 2;
            if((mid == arr.length-1 || arr[mid+1] > x) && (arr[mid] == x))
            {
                return mid;
            }
            else if(arr[mid]>x)
            {
                return lastOccurPos(arr, x, start, mid-1);
            }
            else
            {
                return lastOccurPos(arr, x, mid+1, end);
            }
        }
        else 
            return -1;
    }
    public static void main(String args[])
    {
        int [] arr = {1,2,2,2,2,2,2,2,3,4,5,5,6};
        int x = 2;
        InterviewDesk cnt = new InterviewDesk();
        int r = cnt.freqOfx(arr, x);
        System.out.println(r);
    }
}
Output:
7
Time Complexity: O(logn) and Space Complexity: O(1)
,  

Generate a sum tree of given binary tree

Problem: Given a Binary Tree where each node has positive and negative values. Convert this to a tree where each node contains the sum of the left and right sub trees in the original tree. The values of leaf nodes are changed to 0.

For example:

Approach: The best approach is to do a traversal of the given tree. In the traversal, store the old value of the current node, recursively call for left and right sub trees and change the value of current node as sum of the values returned by the recursive calls. Finally return the sum of new value and value (which is sum of values in the sub tree rooted with this node).
#include <bits/stdc++.h>
using namespace std;
 
struct node{
    int data;
    node *left, *right;
};
 
node* newNode(int data)
{
    node *temp = new node();
    temp->data = data;
    temp->left=NULL;
    temp->right=NULL;
}
 
int sumTree(node *root)
{
    /* If the node is leaf node */
    if(root==NULL)
        return 0;
    /* old_val store the original val
       of node before modification */
    int old_val = root->data;
 
    /* Recursively call the function for left tree and
       right tree and store the sum as the new val of the node */
    root->data = sumTree(root->left) + sumTree(root->right);
 
    /* Return the sum of values of nodes in left and
       right subtrees and old_value of this node */
    return root->data + old_val;
}
 
/* Inorder traversal for printing the output */
void inorder(node *root)
{
    if(root==NULL)
        return;
    inorder(root->left);
    cout<<root->data<<" ";
    inorder(root->right);
}
 
int main()
{
    node *root = newNode(10);
    root->left = newNode(-2);
    root->right = newNode(6);
    root->left->left = newNode(8);
    root->left->right = newNode(-4);
    root->right->left = newNode(7);
    root->right->right = newNode(5);
 
    cout<<"Given Tree"<<"\n";
    inorder(root);
    cout<<"\n";
 
    sumTree(root);
 
    cout<<"Sum Tree"<<"\n";
    inorder(root);
    cout<<"\n";
 
    return 0;
}
Output:
Given Tree
8 -2 -4 10 7 6 5 
 
Sum Tree
0 4 0 20 0 12 0