Saturday, 25 January 2014

Sum of all the numbers that are formed from root to leaf paths.

Question :

Given a binary tree, where every node value is a Digit from 1-9 .Find the sum of all the numbers which are formed from root to leaf paths.
For example consider the following Binary Tree.



 Solution :

The idea is to do a preorder traversal of the tree. In the preorder traversal, keep track of the value calculated till the current node, let this value be val. For every node, we update the val as val*10 plus node’s data.


Answer is : 632 + 6357 + 6354 + 654 = 13997

 Code :


package Tree;

/**
 * Created by Aniket on 1/24/14.
 */
public class TreePathSummer {

    public static int treePathSum(TreeNode root, int val){

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

        val = val * 10 + root.getData();

        if(root.getLeftNode() == null && root.getRightNode() == null){
            return val;
        }

        return treePathSum(root.getLeftNode(),val) + treePathSum(root.getRightNode(),val);

    }

    public static void main(String args[]){
        TreeNode rooTreeNode = new TreeNode(6);

        TreeNode l = new TreeNode(3);
        TreeNode r = new TreeNode(5);

        TreeNode ll = new TreeNode(2);
        TreeNode lr = new TreeNode(5);

        TreeNode lrl = new TreeNode(7);
        TreeNode lrr = new TreeNode(4);

        TreeNode rr = new TreeNode(4);

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

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

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

        r.setRightNode(rr);

        System.out.println("Answer is = " + TreePathSummer.treePathSum(rooTreeNode,0));
    }
}

And the output is as expected

Answer is = 13997

For the java code corresponding to TreeNode data structure refer to the earlier post.

Tuesday, 21 January 2014

Converting Array to a balanced BST(Binary Search Tree)

Question : 

Given an array you need to convert it into an balanced BST(Binary Search Tree).

Example :

Solution :

Given an array first step would be to sort it. You can probably use quick sort which will take average time O(NlogN) complexity. Once you have sorted you can apply following algorithm to convert it into a balance BST.

  1. Get the Middle of the array and make it root.
  2. Recursively do same for left half and right half.
    1. Get the middle of left half and make it left child of the root created in step 1.
    2. Get the middle of right half and make it right child of the root created in step 1.
TreeNode data structure

package Tree;

/**
 * Created by Aniket on 1/22/14.
 */
public class TreeNode {

    int data;
    TreeNode leftNode;
    TreeNode rightNode;

    public TreeNode(int data){
        this.data = data;
    }

    public TreeNode getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(TreeNode leftNode) {
        this.leftNode = leftNode;
    }

    public TreeNode getRightNode() {
        return rightNode;
    }

    public void setRightNode(TreeNode rightNode) {
        this.rightNode = rightNode;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}



 Code to transform a sorted array into balance BST.

package Tree;

import java.util.Arrays;

/**
 * Created by Aniket on 1/22/14.
 */
public class ArrayToBST {

    public static TreeNode convert(int[] ar, int start, int end){

        if(start > end)
            return null;

        int mid = start + ((end - start)/2);
        TreeNode root = new TreeNode(ar[mid]);
        root.setLeftNode(convert(ar,start,mid-1));
        root.setRightNode(convert(ar,mid+1,end));

        return root;

    }

    public static void main(String args[]){

        int array[] = new int[]{1,2,3,4,5,6,7};
        System.out.println("Array is : " + Arrays.toString(array));


        System.out.println("BST in pre order : ");
        PrintTree.printPreOrderTraversal(ArrayToBST.convert(array,0,array.length-1));

    }

}

and the output is

Array is : [1, 2, 3, 4, 5, 6, 7]
BST in pre order :
Data : 4
Data : 2
Data : 1
Data : 3
Data : 6
Data : 5
Data : 7



Pre-order traversal is a type of tree traversals. You can take a look at the types and code for each in the previous post on Tree traversal.

Saturday, 18 January 2014

Building Java projects with Maven.

In last post we saw what is maven and how do we install it. Now lets create a java project and use maven to build and then  test by running it.

What you will need?

  1. Maven installed
  2. JDK(6 or higher)
  3. IDE(Eclipse/Intellij IDEA) or a text editor(gedit/vim)

Setting up the project

Projects that are to be built by maven must follow a particular directory pattern. For detailed directory structure you can visit their documentation on directory structure.

For our example we are going to create a HelloWorld sample inside a package called hello.

So our directory structure will be something like





So go ahead and create such structure. You can use following command

mkdir -p src/main/java/hello

Now inside hello directory create two java files - HelloWorld.java  and Greeter.java.

Code for them is provided below. For src/main/java/hello/HelloWorld.java

package hello;

public class HelloWorld {
    public static void main(String[] args) {
        Greeter greeter = new Greeter();
        System.out.println(greeter.sayHello());
    }
}

and for src/main/java/hello/Greeter.java

package hello;

public class Greeter {
    public String sayHello() {
        return "Hello world!";
    }
}



Now that Maven is installed, you need to create a Maven project definition. Maven projects are defined with an XML file named pom.xml. Among other things, this file gives the project’s name, version, and dependencies that it has on external libraries.

Note :  This file must be in the project root directory which means in the folder which has src folder.

Create a file named pom.xml at the root of the project and give it the following contents:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>HelloWorld</groupId>
    <artifactId>gs-maven-initial</artifactId>
    <version>0.1.0</version>
    <packaging>jar</packaging>
</project>

Now you can build your java project using 

mvn compile

This will download your dependencies and compile you java files. Corresponding .class files will be created in a target folder in the projects root folder.

To make the jar file of your project you can use

mvn package

This will create a jar file in the target folder. Now you can run your code with

java -jar PathToYourJarFile

Maven Build lifecycle

compile and package were some of the initial phases of Maven build lifecycle. All of them are listed in the following diagram



For more details on the maven build life cycle phases you can visit their official site.

I am getting Can't execute jar- file: “no main manifest attribute”. What should i do?

That is because you have not told maven while packaging how do you built the project. You need to provide build information withing <build> and </build> tags in the build file. You can add following tag between <project> and </project>.


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>hello.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

and you are done. By this you essentially say what is your main class so that while executing java knows the entry point from that jar file.

I want to use IDE instead of text editor. How do I import maven projects to my IDE?

Even this is very simple. You can run the following commands in the projects root directory -

  • mvn eclipse:eclipse  (For Eclispe IDE)
  • mvn idea:idea  (For intellij IDEA IDE)
For example idea command will generate all the required files like .ipr(project file), .iws(workspace file) etc. You can open the file by simply opening this .ipr file in IDEA.

Note : As per Mavens official site mvn idea:idea is obsolete. You can directly do File -> Import project and select pom.xml file.

I am getting "Package name does not correspond to the file path" error after importing project in my IDE.

This is because dash(-) is not allowed in package name and your -DgroupId contained  dash(-) which was used as package name. You can refactor and replace dash(-) with underscores(_) which is legal in a package name.



How to install maven on Ubuntu?

What is Maven?

Maven is essentially a build automation tool similar to apache ant but provides much more features that just building. It addresses two important aspects -  
  1. how your software will be built and 
  2. your software dependency resolution
For complete details you can visit the following sites
  1.  Wiki
  2. Apache Maven Homepage
Lets get started then.



How to install Maven?

 You can search for the maven package using the following command

apt-cache search maven


You may see a lot of packages but what we are interested is -

maven - Java software project management and comprehension tool

So lets go ahead and install it. Use the following command to install the package

sudo apt-get install maven

I am using Ubuntu so I have apt-get. You can use yum  if you have Fedora/CentOS.

To verify the installation you can simply execute the following command

 mvn -v

v here stands for version. You can also type complete word i.e  mvn -version.
 You will see some details about the installed maven package.

This indicated maven is successfully installed.

Install latest versions

Using apt-get you may not get the latest version of maven. For latest version download the binary from maven site and install it.

Use the following commands - 

  1. cd ~/Downloads
  2. wget http://apache.mirrors.timporter.net/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
  3. sudo mkdir -p /usr/local/apache-maven
  4. sudo mv apache-maven-3.1.1-bin.tar.gz /usr/local/apache-maven
  5. cd /usr/local/apache-maven
  6. sudo tar -xzvf apache-maven-3.1.1-bin.tar.gz
  7. Edit ~/.profile with gedit ~/.profile and add these four lines:
    1. export M2_HOME=/usr/local/apache-maven/apache-maven-3.1.1
    2. export M2=$M2_HOME/bin
    3. export MAVEN_OPTS="-Xms256m -Xmx512m"
    4. export PATH=$M2:$PATH


Next immediate question that may come to anyone’s mind - 

Where is maven installed?

Maven by default gets installed in the following directory

/usr/share/maven


and maven configuration files go to the following directory

/etc/maven


settings.xml has default configurations like path to local repository. yes maven downloads dependencies and stores it in a local repository so that there is no need to download same dependency twice.

Path to maven(mvn) executable is not added to $PATH variable then how is the command recognized?

If you print your path variable by using

echo $PATH

You will notice one of the paths in the variable is

/usr/bin

Now if you see the contents of /usr/bin you will notice that it has mvn executable. It is actually soft link to the actual executable. This approach is a common approach. We cannot keep adding all installed packages folder to $PATH. Instead create a soft link to executable and keep it in  /usr/bin and add this to the $PATH.

This was just how do we install maven on ubuntu. In the next post we will see how to compile and run Java code using maven.


Related Links

Tuesday, 14 January 2014

Race Condition, Synchronization, atomic operations and Volatile keyword.

In this times where multi-threading is an essential feature of almost all systems it is very important for the programmers to handle race conditions. All the concepts mentioned in the title of this post - Race Condition, Synchronization, atomic operations and Volatile keyword are very much related to each other and understanding them together will give you a better and bigger picture of Concurrency.

Race Condition

Consider a very simple increment(++) operation. There is a common misconception that incrementing is an atomic operation. If you are wondering what atomic operations are then be patient. We will discuss it in a more detail later. For now you can understand atomic operation as an operation that takes only one CPU cycle.

But is is not. Incrementing is not an atomic operation. If you think a bit deeper you can imagine increment operation as sequence of following operations.
  1. Read the value from the memory.
  2. add one to it.
  3. Write the changed value back to the memory.
Individual operations may or may or may not be atomic in nature(Will cover this in volatile section). But for our current discussion lets say the counter is of type int  and read/writes for it are atomic. That means as far as our discussion on race condition using increment is considered each subdivided operations mentions above happen in a single CPU cycle.

Now lets see where the problem arises.Lets say we have a single counter instance and it's value is 17. Lets say you have two thread T1 and T2. Both perform increment operation on the same counter instance so that the result we expect at the end is 19. Lets say T1 reads the value of the counter which is 17 and then context switch happens. Then T2 reads the value which is again 17. Now lets say T2 will increment the value to 18 and store it back in the memory. Now the T1 thread again increments the value it has(17) so that the result is 18 and stores it back in the memory which overwrites the T2 threads value. So at the end your value is 18 when you expected it to be 19.  This problem is called race condition. You can visualize the problem with following diagram -


So yes this a problem that every programmer faces while programming in multi-threaded environment. So what is the way out? One could say make an machine level increment operation that happens in a single CPU cycle(or in other words make the increment operation atomic). But we cannot make those machine level changes can we? There are other alternatives or work a rounds that will help us solve the problem. And the first one of it is called - Synchronization.

Synchronization

To avoid race conditions we can use synchronization. By synchronizing a part of code we ensure that only one thread can process that part of the code. In java either you can have synchronized methods or blocks.

Now even these methods or blocks can be further categorized into - 
  1. instance methods/blocks
  2. static/class methods/blocks
To understand the difference between above two it is essential to understand how synchronization mechanism works internally. Java is an Object oriented programming language and everything in it is essentially an Object. Each Object is associated with a monitor. Synchronization involves e thread getting a lock over this monitor. If one thread has a lock over the monitor other thread cannot acquire the lock and consequently cannot access the area governed by that monitor.

Now for instance methods lock is acquired for monitors of the instance itself. So for example if you have a getData()  method of the Employee class then the lock obtained is on the individual Employee instance.

On the other hand for static methods lock obtained is over Class instance of the Employee instance. You can get this Class object by using ClassName.class or classInstance.getClass() method. And this Class instance is same for all the individual Employee instances.

Refer : Interview Question #13 synchronization on static function/method.

So for above counter problem we can synchronize the increment operation with a synchronized function or a block. Eg.

    public synchronized void incrementCounter(){
        counter++;
    }


This involves obtaining lock on the instance or this and then increment. So as long as one thread is carrying out an increment operation no other thread can enter this function. Analogous synchronized block would be

    public void incrementCounter(){
        synchronized (this) {
            counter++;
        }
    }


That is all about the basics of synchronization. We may go into more detailed discussion in another post. But the basic concept of what is synchronization and why is it used should be clear by now.

Note :

Java synchronized keyword is re-entrant in nature it means if a java synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock.(More on Synchronization)


Synchronization is an alternative for operations that are not atomic. So now lets see what atomic operations are.

Atomic operations

As mentioned previously each higher level language operation may require one or more CPU cycles to be completed. It is very much possible that before all the cycles needed for a particular operation are completed there may be context switch and some other process or thread might take control of the CPU resulting in race condition we discussed above. Though we cannot actually manipulate processor instructions there are work a rounds to make an operation atomic.

If you have encountered this context before you must have read -

"The Java language specification guarantees that reading or writing a variable is an atomic operation(unless the variable is of type long or double). Operations variables of type long or double are only atomic if they declared with the volatile keyword."

Even if not lets see what it means. It means read and writes of primitive variables are atomic in nature. Exception to this is long and double.

So why the exception?
Answer : It's not atomic because it's a multiple-step operation at the machine code level. That is, longs and doubles are longer than the processor's word length. So on a machine where processor's word length is greater than the long/double size it is possible for the corresponding read write operations to be atomic.

Note :   Also note it says only read and write. So do not confuse it with any other operation like incrementing, As mentioned above increment operation itself is composed of 3 sub operations listed above.

As per JLS

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values. 


So another way to make read/write for long/double is to declare them volatile. I have just mentioned it here since it comes under atomic title but will discuss it more in next topic - Volatile variables.

Java specially provides atomic classes for purposes like this. For eg we have AtomicInteger or AtomicLong that provides methods like getAndDecrement(), getAndIncrement() and getAndSet() which are atomic.

The AtomicInteger class uses CAS (compare-and-swap) low-level CPU operations (no synchronization needed!) They allow you to modify particular variable only if the present value is equal to something else (and return it it succeed). So when you execute getAndIncrement() it actually runs in a loop (simplified real implementation):

int current;
do {
  current = get();
} while(!compareAndSet(current, current + 1)


Volatile keyword

Synchronization solves the problem faced due to race conditions but there is one another problem that we have missed and that is -  visibility.

Consider following code


public synchronized Singleton getInstance(){
if(_instance == null){   //race condition if two threads sees _instance= null
_instance = new Singleton();
}
}


 Here synchronization makes sure that only one thread enters the function and no other thread is allowed to access it until the thread which has the lock over it's monitor completes it's execution. But what about the variable visibility?

Thread T1 lets say identifies that  _instance is null. It acquires lock and creates new object but before the it comes out of the function lets say there is a context switch. Though new variable is created some other thread in some other function will still see _instance as null . This is because each thread caches the value of a variable and the synchronization among threads happen only when the synchronized method or block is completely executed. To overcome this problem we use volatile keyword.

Volatile keyword in Java guarantees that value of volatile variable will always be read from main memory and not from Thread's local cache thus solving the visibility issue.

Now lets come to the Long and Double issue and how making it volatile make it's read and write atomic. So there is this another concept  - happens before relationship that volatile keyword follows which means if there is a write operation with subsequent reads then reads will be processed only after write is successful.

Useful Links

This post is meant to clear the basic concepts of concurrency in Java and give you a bigger picture of how above topics are correlated. Maybe we will have individual posts to learn them individually. But you can refer to following links. They provide quite useful information.
I would recommend read following book for a good exposure on Java concurrency -
  • Java concurrency in practice - Book by Brian Goetz

t> UA-39527780-1 back to top