Monday, 3 March 2014

HeapSort in Java

Heap Sort sorts an array in place with time complexity O(N log N). Following is the code to do the same

Binary Heap

A binary heap has two following two properties

  1. Structural property : All levels except the last are full. Last level is left filled.
  2. Heap property : Priority of node is at least as large as it's parent (This is true for min heap but similarly you can have max heap where priority of parent is at least as large as it's children)

Code :

package Sorts;

import java.util.Arrays;

/**
 * Created by Aniket on 3/3/14.
 */
public class HeapSort {

    public int getLeft(int i){
        return 2*i;
    }

    public int getRight(int i){
        return 2*i+1;
    }

    public int getParent(int i){
        return i/2;
    }

    public void maxHeapify(int[]  array, int position){

        int leftPosition = getLeft(position);
        int rightPosition = getRight(position);

        int largest = 0;

        if(leftPosition <= array.length && array[leftPosition-1] > array[position-1]){
            largest = leftPosition;
        }
        else {
            largest = position;
        }
        if(rightPosition <= array.length && array[rightPosition-1] > array[largest-1]){
            largest = rightPosition;
        }

        if(largest != position){
            swap(array,position-1,largest-1);
            maxHeapify(array, largest);
        }
    }

    public void maxHeapifyForSort(int[]  array, int position, int maxPos){

        int leftPosition = getLeft(position);
        int rightPosition = getRight(position);

        int largest = 0;

        if(leftPosition <= maxPos && array[leftPosition-1] > array[position-1]){
            largest = leftPosition;
        }
        else {
            largest = position;
        }
        if(rightPosition <= maxPos && array[rightPosition-1] > array[largest-1]){
            largest = rightPosition;
        }

        if(largest != position){
            swap(array,position-1,largest-1);
            maxHeapifyForSort(array, largest,maxPos);
        }
    }

    public void buildMaxHeap(int[] array){

        for(int i=(array.length)/2;i>0;i--){
            maxHeapify(array,i);
        }

    }

    public void swap(int[] array, int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public void heapSort(int[] array){
        buildMaxHeap(array);
        for(int i=array.length;i>0;i--){
            swap(array,0,i-1);
            maxHeapifyForSort(array,1,i-1);
        }
    }

    public static void main(String args[]){

        int[] array = new int[]{4,1,3,2,16,9,10,14,8,7};
        System.out.println("Original Array : " + Arrays.toString(array));
        //new HeapSort().buildMaxHeap(array);
        new HeapSort().heapSort(array);
        System.out.println("After Sorting Array : " + Arrays.toString(array));


    }

}

Output : 

Original Array : [4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
After Sorting Array : [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]


 NOTE: I have shown two similar methods here maxHeapify(int[]  array, int position)
and maxHeapifyForSort(int[]  array, int position, int maxPos) but for sorting you will only need the second one. If your goal is to only create a max heap method one will do just fine. When we go for sort in each iteration we need to decouple indexes from the end so they are the maximum ones and hence we need a limit position to inform heapify function till where it should operate. What heapify does is that each element should have children which are smaller then itself.


NOTE:  Heap sort is an in-place algorithm (in-place algorithm is an algorithm which transforms input using no auxiliary data structure).


Applications :  Heaps are generally used in priority queues ( min or max heap) so that you can retrieve the min or max element in O(1). Insertion will be log(N). It can be used to store realtime data. Lets say to keep score of top 3 people in a game given their scores are changing in realtime.

Related Links

Wednesday, 26 February 2014

Infix to Postfix and Prefix conversion

Question :

Question is simply to covert a given infix expression to both prefix as well as postfix notation. The postfix part of the question is picked up from the code chef question --> Transform the Expression . I have simply extended it to output prefix part as well.

Code :

package CodeChef;

import java.util.Stack;

/**
 * Created by Aniket on 2/23/14.
 */
public class PostFixConverter {

    public static void main(String args[]){
        String infix = "((a+b)*(z+x))";
        System.out.println("Postfix : " + printPostFix(infix));
        System.out.println("Prefix : " + printPreFix(infix));

    }

    public static String printPostFix(String str){
        Stack stack = new Stack();
        String postfix = "";
        for(int i=0;i<str.length();i++){
            char c = str.charAt(i);
            if(Character.isLetter(c)){
                postfix = postfix + c;
            }
            else if(c == '('){
                continue;
            }
            else if(c == ')'){
                postfix = postfix + ((Character)stack.pop()).toString();
            }
            else{
                stack.push(c);
            }
        }
        return postfix;

    }

    public static String printPreFix(String str){
        Stack stack = new Stack();
        String prefix = "";
        for(int i=str.length()-1;i>=0;i--){
            char c = str.charAt(i);
            if(Character.isLetter(c)){
                prefix = ((Character)c).toString() + prefix;
            }
            else if(c == '('){
                prefix = ((Character)stack.pop()).toString() + prefix;
            }
            else if(c == ')'){
                continue;
            }
            else{
                stack.push(c);
            }
        }
        return prefix;

    }

}


Output :

Postfix : ab+zx+*
Prefix : *+ab+zx

Note :

 Note that the expression provided as input is well bracketed input and hence we are not taking care of ordering. If the question asks for ordering then you need to take care of that as well. For example if infix expression in a+b*c answer(post fix) would be abc*+ and not ab+c*.

MCQ #14

Question : 

There are two code snippets given below. You have to predict output for both.

First :

String str1="str";
String str2="ing";
String concat=str1+str2;

System.out.println(concat=="string");

Second :

final String str1="str";
final String str2="ing";
String concat=str1+str2;

System.out.println(concat=="string");

In both case answer will be either true or false.

Answer : 

Answer is 1st case is false.
Answer in 2nd case is true.

Explanation :

When Java code is compiled, compiler does some optimizations of it's own. An expression that is know to not change during runtime is know as compile time constant expression. So lets say if you have a String
String concat = "str" + "ing";
after compilation it becomes
String concat = "string";
So if question is framed like how many String instances are created in above java code then the answer is one. String literals are interned. So lets come to our problem

  1. (False)In first case Strings are not final. Also as we know String is immutable in nature. Concatenation of two String literals yields a new String instance and hence the answer on comparison would be false.
  2. (True)In second case Strings are defined as final. That equivalently means the Strings will not change at runtime and hence they form compile time constant expression. So when the code is compiled concat actually points to "string" literal(which is interned as all String literals are). Now since we are comparing this with another String literal with same content both will point to same String instance in the String pool. So the answer in this case would be true.   

Important Links

  1. Difference between using == operator and equals() method in Java
  2. Comparing strings with == which are declared final in Java
  3. how many java String objects will be created in the statement String s=“abc”+“xyz”

Monday, 24 February 2014

Mounting Solaris NFS Share on Linux(Ubuntu)

Basics

  1. When we say we are sharing/mounting partition of one machine on another machine there are some prerequisites that must be first understood and taken care of. First of all both machines must be connected via some network or in other terms both machine must be accessible to each other. How do we check that? -> Simply open command prompt and execute

    ping IPAddress of other machine (Eg. ping 192.168.1.202)

    If the ping is successfull in both ways we are good to proceed.
  2. To fully understand point mentioned above it is important to know that mounting a partition to another machine essentially involves a server-client architecture. The machine whose partition is to be share acts as a server where as machine on which the partition is to be mounted acts as a client.
  3. When we say we have server-client architecture what immediately comes into mind is what rules govern the communication between server and client. More precisely it is called protocol. For eg. files can be shared over FTP(File transfer protocol). For mounting partitions over network we have different set of protocols. Most commonly used are Network File System (NFS) for Linux and Common Internet File System (CIFS) for Windows.
  4. As long as we are on mounting topic it would be beneficial to revise mount and umount System calls as they will be used later.

Before we proceed to see how Solaris partition/share is mounted on a Linux machine you may want to go though how Linux share is mounted on another Linux machine. Following link also provides the basics like installing portmap, understanding exports, mount, umount etc.

How To Set Up an NFS Mount on Ubuntu 12.04 


Mounting Solaris NFS Share on Linux

  1. Create directory on your Solaris machine which you wish to share. Next provide permissions to that directory. You can either use chmod command or you can change permissions from file properties.

  2. By default Solaris or rather mostly all unix based systems have Bourne shell(sh). If you are more comfortable with Bourne Again Shell(bash) like me you can easily switch to it. Steps provided in screen shot below -

  3. Next step is to check if NFS server is up and running. For that you can execute following command in the console -

    svcs | grep nfs

    If you get the output as shown in the screen shot below you are good to proceed. If not then you have to start the nfs server. You can do that with following command -

    svcadm -v enable network/nfs/server
    Similar command goes for disabling the server

    svcadm -v disable network/nfs/server

    Info :
    svcs :- report service status
    For more info execute man svcs on console
    svcadm :- System administation command. Manipulate service instance.
    For more info execute man svcadm on console
  4. Next you need to make an entry of the directory you are going to share in the file /etc/dfs/dfstab. Add following lines to the file and save.(Note : You need su privileges to edit the file).

    #share [-F nfs] [-o specific-options] [-d description] pathname
    share  -F nfs -o rw -d "TestDescription" /Desktop/aniket/mount


  5. Save the changes above and restart the server.Infact for any further changes in this file to take effect you will have to bring down the server amd restart.

    svcadm -v disable network/nfs/server
    svcadm -v enable network/nfs/server
    After restarting the server you can check that that the entry is successfull by executing command - share.
    If you are able to see the entry, execute the command - shareall.
    This will inform your server that the directory represented by the entry made can be shared over the network.
  6. That is all for server(Solaris) side. Now lets move on to Client(Linux/Ubuntu) side. Here you simply need to execute mount system call.

    sudo mount -vt  nfs 192.168.1.202:/Desktop/aniket/mount /home/aniket/SolarisShared/mount/

    or if you wish to remount you can do

    sudo mount -o remount -vt  nfs 192.168.1.202:/Desktop/aniket/mount /home/aniket/SolarisShared/mount/

    By syntax you must have guessed the format is

    mount -vt nfs serverIP:/serverDirPath localDirPath

  7. Finally you can see if the directory is really mounted/mapped. You can see it physically or use the command - mount




Thats all! Let me know if there are any further doubts.

Saturday, 22 February 2014

Lowest Common Ancestor in a Binary Search Tree.

Question : 

Given values of two nodes in a Binary Search Tree, write a c program to find the Lowest Common Ancestor (LCA). You may assume that both the values exist in the tree. (GeeksForGeeks)

LCA(Lowest Common Ancestor) :


Let T be a rooted tree. The lowest common ancestor between two nodes n1 and n2 is defined as the lowest node in T that has both n1 and n2 as descendants (where we allow a node to be a descendant of itself). 

The LCA of n1 and n2 in T is the shared ancestor of n1 and n2 that is located farthest from the root. Computation of lowest common ancestors may be useful, for instance, as part of a procedure for determining the distance between pairs of nodes in a tree: the distance from n1 to n2 can be computed as the distance from the root to n1, plus the distance from the root to n2, minus twice the distance from the root to their lowest common ancestor. (Source Wiki

Example :





For example, consider the BST in diagram, LCA of 10 and 14 is 12 and LCA of 8 and 14 is 8.


Solution :

We can solve this problem using BST properties. We can recursively traverse the BST from root. The main idea of the solution is, while traversing from top to bottom, the first node n we encounter with value between n1 and n2, i.e., n1 < n < n2 or same as one of the n1 or n2, is LCA of n1 and n2 (assuming that n1 < n2). So just recursively traverse the BST in, if node's value is greater than both n1 and n2 then our LCA lies in left side of the node, if it's is smaller than both n1 and n2, then LCA lies on right side. Otherwise root is LCA (assuming that both n1 and n2 are present in BST)

Code : 

package Tree;

/**
 * Created by Aniket on 2/22/14.
 */
public class LCAFinder {

    public static TreeNode findLCA(TreeNode root, int n1,int n2){

        if(root == null){
            return null;
        }

        int data = root.getData();
        if(data > n1 && data > n2){
            return findLCA(root.getLeftNode(),n1, n2);
        }

        if(data < n1 && data < n2){
            return findLCA(root.getRightNode(), n1, n2);
        }
        return root;
    }

    public static void main(String args[]){

        TreeNode root = new TreeNode(20);

        TreeNode l = new TreeNode(8);
        TreeNode r = new TreeNode(22);

        TreeNode ll = new TreeNode(4);
        TreeNode lr = new TreeNode(12);

        TreeNode lrl = new TreeNode(10);
        TreeNode lrr = new TreeNode(14);

        root.setLeftNode(l);
        root.setRightNode(r);

        l.setLeftNode(ll);
        l.setRightNode(lr);

        lr.setLeftNode(lrl);
        lr.setRightNode(lrr);

        System.out.println("LCA : " + findLCA(root,10,14).getData());
    }
}

Output : 

LCA of Node with data 10 and 14 : 12
(You can similarly execute the code for 8 and 14( Answer is 8))

Important Links : 

  1. Lowest common ancestor
  2. How to find the lowest common ancestor of two nodes in any binary tree?
  3.  Lowest Common Ancestor in a Binary Tree. (OSFG)



t> UA-39527780-1 back to top