Tuesday, 21 April 2015

Find intersecting node between 2 Linked List

Kind of data structure questions which are normal in C language because C has pointers, so we have address of each memory location. But when we take java into consideration we don't have any pointer to judge whether nodes are same or not except double equal check( i.e. reference check). And then java.util.collections package comes to rescue us.

There are a number of ways by which you can solve the problem but important things are time and space complexity. It matters a lot when you are designing a highly scalable system where performance matters a lot and other side of story is "space comes at premium" which cannot be ignored.

Now let me put the problem statement into diagrammatic representation so that it would be easy to understand.

So here intersecting node is 45 which is first common element in both the linked list.

Time to start with my version of solution which is not very good from space complexity point of view but takes linear time complexity.

Before we start a very good point about IdentityHashMap is that it does reference matching i.e. double equals check not .equals() matching. So we are going to take this advantage in our algorithm.

Alogrithm steps:
1. Create an IndentityHashMap.
2. iterate through list 1 and put all nodes as key into IdentityHashMap.
3. iterate through list 2 and do containsKey check for all nodes in list2. Which ever containsKey returns true is the intersecting node between 2 linked list.

Time Complexity: O(n + m) linear order where n= elements in list1 and m= elements in list2
Space Complexity: O(n) linear order where n = elements in list1.

So far we are done with our algorithm design and need to jump start with code:

1. Below is pojo class which represents individual node in linked list.

 public class Node<T> {  
      private T value;  
      private Node<T> next;  
      public T getValue() {  
           return value;  
      }  
      public void setValue(T value) {  
           this.value = value;  
      }  
      public Node<T> getNext() {  
           return next;  
      }  
      public void setNext(Node<T> next) {  
           this.next = next;  
      }       
 }  

2. Main class where intersection logic written:

 import java.util.IdentityHashMap;  
 import java.util.Map;  
 public class IntersectionExample {  
      public static void main(String[] args) {  
           Node<Integer> list1 = new Node<Integer>();  
           list1.setValue(20);  
           Node<Integer> node1 = new Node<Integer>();  
           node1.setValue(60);  
           Node<Integer> node2 = new Node<Integer>();  
           node2.setValue(90);  
           Node<Integer> node3 = new Node<Integer>();  
           node3.setValue(45);  
           Node<Integer> node4 = new Node<Integer>();  
           node4.setValue(23);  
           node4.setNext(null);  
           list1.setNext(node1);  
           node1.setNext(node2);  
           node2.setNext(node3);  
           node3.setNext(node4);  
           Node<Integer> list2 = new Node<Integer>();  
           list2.setValue(9);  
           Node<Integer> point1 = new Node<Integer>();  
           point1.setValue(5);  
           Node<Integer> point2 = new Node<Integer>();  
           point2.setValue(8);  
           list2.setNext(point1);  
           point1.setNext(point2);  
           point2.setNext(node3);       
           getIntersection(list1, list2);  
      }  
      public static void getIntersection(Node<Integer> list1, Node<Integer> list2){  
           final Integer constant = 1;  
           Map<Node<Integer>, Integer> map = new IdentityHashMap<Node<Integer>, Integer>();  
           while(list1 != null){  
                Node<Integer> current = list1;  
                map.put(current, constant);  
                list1 = list1.getNext();  
           }  
           while(list2 != null){  
                Node<Integer> current = list2;  
                if(map.containsKey(current)){  
                     System.out.println("Intesecting Node, value: "+current.getValue());  
                 break;  
                }  
                list2 = list2.getNext();  
           }  
      }  
 }  

Output:

 Intesecting Node, value: 45  

That's all from my end on this post. As there can be a number of ways by which you can solve this problem, looking forward for your contribution. Thanks.

Monday, 20 April 2015

Difference between new Random() and new Random(long seed) constructor behavior

Once again encountered with an interesting thing which I think need to be shared. This is regarding java.util.Random class to generate random numbers in code base and why 2 different constructors provided in Random class, what behavioral changes we are going to achieve using below 2 constructor:
1. new Random();
2. new Random(long seed); 

So we will start our discussion with code examples which covers above constructors.

Example 1 using new Random() constructor:

 import java.util.Random;  
 public class Example7 {  
      public static void main(String[] args) {  
           Random rand = new Random(); //Random instance without seed  
           for(int i=0; i<10; i++){  
                int randomNumber = rand.nextInt(2);  
                System.out.print(randomNumber+", ");  
           }  
      }  
 }  

Output:
 1, 0, 0, 1, 1, 0, 1, 1, 0, 1,   

(Please note output varies from system to system and execution to execution)

Example 2 using new Random(long seed):


 import java.util.Random;  
 public class Example7 {  
      public static void main(String[] args) {  
           Random rand = new Random(2); //Random instance with seed  
           for(int i=0; i<10; i++){  
                int randomNumber = rand.nextInt(2);  
                System.out.print(randomNumber+", ");  
           }  
      }  
 }  

Output:

 1, 0, 1, 0, 0, 1, 1, 0, 1, 1,   

Now with example 2 you will see that you will get same set of result irrespective of how many time you execute example 2.

But at the same time with example 1 where we used new Random() constructor we will get different set of number on different executions.

Till this we can say that definitely it is "seed" parameter which is responsible for giving same set of random numbers every time.

Time to dig to down to "long seed" parameter to understand the behaviour.

If you check the implementation of default constructor of Random class it uses seed value which will be different for every Random class object creation, where as for parametrized constructor of Random, seed value would be same for each object creation with same seed value.

So no matter how many random objects you create with same seed value, there sequence would be same. Also above statement is true for individual execution also.

If you want go to further into deep, better place would be to check code under Random class. It uses "linear congruential pseudo random number generator" to produce random number..to be honest still trying to understand the algorithm behind it :-)

That's all from my end on Random class. Let me know if you can add something more into it, definitely I am looking forward to update the post.

Friday, 17 April 2015

Smart Java 7 JIT Complier

I don't know about other guys but definitely I used System.currentTimeMillis() to calculate method execution time while doing performance analysis using junits.

This post will cover how things can go completely wrong with such kind of performance testing.

Before we deep dive into the issue let me put a code snippet to explain the issue in better manner:

 public class APSum {  
      public static void main(String[] args) {  
           long then = System.currentTimeMillis();  
           ArithmeticProgression.sum(500000000);  
           long now = System.currentTimeMillis();  
           System.out.println("Elapsed time: " + (now - then));  
      }  
 }  
 class ArithmeticProgression{  
      public static double sum(int i){  
           double sum=0;  
           for(int index=0; index<=i; index++){  
                sum = sum + (double)index;  
           }  
           return sum;  
      }  
 }  

 As we can see in above code, system is calculating sum of numbers starting from zero to provided input number and returning the result. Also we are calculating execution time of method sum using  System.currentTimeMillis().

Now by going through code we can say that total execution time calculation depends on for loop which executed 500000000 time and "sum = sum + (double)index" calculation.

Here our thinking can go wrong with respect to JIT compiler and reason to say that JIT compiler is too much smart.

Let us understand sample of how JIT optimization works:
1. As you can see in main method, we haven't used variable returned from ArithmeticProgression sum method.
2. So when JIT see such kind of code which doesn't mean anything to caller, it just run empty for loop without doing any calculation of "sum = sum + (double)index".

So our assumption of calculating execution time can go completely wrong with the case.

Bottom line is JIT compiler uses a lot of background algorithm to optimize our code while running.

Note:
1. JIT compiler optimization is highly platform dependent so you cannot expect same behaviour across different platform.
2. Scenario is hard to reproduce on local system eclipse as JIT works on compilationThreshold flag of JVM so JIT comes into picture only when compilation reaches over compilationThreshold value.