HackerRank: Sparse Arrays

Problem Statement

There are N strings. Each string’s length is no more than 2020 characters. There are also Q queries. For each query, you are given a string, and you need to find out how many times this string occurred previously.

Input Format

The first line contains N, the number of strings.
The next N lines each contain a string.
The N+2nd line contains Q, the number of queries.
The following Q lines each contain a query string.

Constraints

1N1000
1Q1000
1lengtof anstring20

Sample Input

4
aba
baba
aba
xzxb
3
aba
xzxb
ab

Sample Output

2
1
0

Explanation

Here, “aba” occurs twice, in the first and third string. The string “xzxb” occurs once in the fourth string, and “ab” does not occur at all.

Solution

The water jug problem

We have three water jugs, and each can hold 3oz., 5oz., and 8oz. of water, respectively.
Without the possibility of water spilling when poured from one jug to another, and given that the jugs have no calibration, how do we divide the 8oz. of water equally among two jugs?

We will define a class named State holding the capacity of A and B jars.
It should be noted that only 2 jars are sufficient to define a state, as water held in third jar can be calculated by subtracting the sum of two from the total.

Define class State like this…

package mystate;
import bfs.threejugproblem.NotSupportedException;
import java.util.ArrayList;
import java.util.List;
public class State
{
int a=0;//3
int b=0;//5
int c=8;//8

public State(int a, int b)
{
this.a=a;
this.b=b;
this.c=8-a-b;
}
public boolean isGoal()
{
return (b==4 && c==4);
}
public boolean equals(Object xx)
{
State x = (State) xx;
if(this.a==x.a && this.b==x.b && this.c==x.c)
{
return true;
}
else
{
return false;
}
}
public int hashCode()
{
return 8;
}
public List getChildren()
{
List children = new ArrayList();
// a -> b
if(a!=0 && b!=5)// if a is not empty
{
if(a+b<=5)
{
children.add(new State(0, a+b));
}
else
{
children.add(new State(a+b-5,5));
}
}
//a->c
if(a!=0 && c!=8)
{
// We are pouring completely from a to c
// a will be 0
// b will be 8-a-c
// c will be a+c
children.add(new State(0, 8-a-c));
}
//b->a
if(b!=0 && a!=3)
{
if(a+b<=3)
{
children.add(new State(a+b, 0));
}
else
{
children.add(new State(3, a+b-3));
}
}
// b->c
if(b!=0 && c!=8)
{
// We are pouring completely from b to c
// a will be 8-b-c
// b will be 0
// c will be b+c
children.add(new State(8-b-c, 0));
}
//c->a
if(c!=0 && a!=3)
{
if(c+a<=3)
{
children.add(new State(c+a, 8-c-a));
}
else
{
// a will be full i.e. 3 liters
// b will be 8-c-a
// c will be c+a-3
children.add(new State(3, 8-c-a));

}
}
// c->b
if(c!=0 && b!=5)
{
if(c+b<=5)
{
children.add(new State(8-c-b , c+b));
}
else
{
children.add(new State(8-c-b, 5));
}
}
return children;
}
@Override
public String toString()
{
return "{"+a+","+b+","+c+"}";
}
}

Depth First Search Algorithm

public class DFSThreeJugProblem 
{
public static void main(String[] args)
{
State currentState = new State(0,0);
List visitedStates=new ArrayList();
// Check if the current State has a solution
// given a set of visited States.
dfs(currentState, visitedStates);
}
public static void dfs(State currentState, List vStates)
{
// if it is GOAL
if(currentState.isGoal())
{
// That's it we are done.
for(State v : vStates)
{
System.out.println(v);
System.out.println(currentState);
}
System.exit(0);
}

// if visisted state contains currentState, then just return.
// This is the wrong branch, and we need not traverse it further.
if(vStates.contains(currentState))
return;

// Add current state to visited states.
vStates.add(currentState);

// Make clone of visited states.
List clonedVStates = new ArrayList(vStates);
// Find the set of possible children of current state.
List children = currentState.getChildren();
for(State c : children)
{
// if a children C is not in the visited states
// again call DFS on current child and visited States.
if(!clonedVStates.contains(c))
{
dfs(c, clonedVStates);
}
}
}
}

Breadth First Search algorithm…

public class BFSThreeJugProblem 
{
private static List visitedStates=new ArrayList();
private static Queue stateQueue = new LinkedList();
public static void main(String[] args) throws NotSupportedException
{
State currentState = new State(0,0);
// Add current state to state Queue.
stateQueue.add(currentState);
do
{
// Get the first Element from Queue.
State firstElementInQueue = stateQueue.peek();
// If the first Element is the Goal
// We are done.
if(firstElementInQueue.isGoal())
{
for(State p : visitedStates)
{
System.out.println(p.toString());
}
// There is no recursion here, so simple return would do.
return;
}
else
{
// Add firstElement to visited States
visitedStates.add(firstElementInQueue);
// Get the children of first element
List children = firstElementInQueue.getChildren();
for(State v : children)
{
// if children has not already been visited.
if(!visitedStates.contains(v))
{
// add the child to state Queue.
stateQueue.add(v);
}
}
// Remove the first element from state queue.
stateQueue.remove(firstElementInQueue);
}
// do this till state queue is empty.
}while(!stateQueue.isEmpty());
}
}

Comparable vs Comparator

There are many articles available on internet for this. But still I would write something about it.

What when and why?

A Comparable class is a class, which can be compared with the objects of its own type. Let us take an example of a book.

public class Book implements Comparable {
    String title;
    int    isbn;

    Book(String title, int isbn) {
        this.title = title;
        this.isbn  = isbn;
    }
    /* This method will be the default method used 
       to sort Book objects in a list or Array */
    public int compareTo(Object object) {
    // It should throw NullPointerException if object passed is null
    if (object==null)
    {
        throw new NullPointerException("compareTo: Argument passed is null");
    }
        Book other = (Book) object;
        if (this.title.equals(other.title)) {
            return this.isbn - other.isbn;
        }
        return this.title.compareTo(other.title);
    }
}

The moment your class implements Comparable, you can then use

List list = new LinkedList();
        list.add(new Book("Patterns", 12345));
        list.add(new Book("Apples", 34567));
        list.add(new Book("Examples", 23456));

        Collections.sort(list);


Using this you can sort your list.

But what if now, you want to add or use another sorting criteria defined in Book class… Here comes the need of Comparator.
There are two ways listed here to use the Comparator class.

First method

We create a anonymous class that implements Comparator and overrides compare method.

Collections.sort(list, new Comparator() {
            public int compare(Object obj1, Object obj2) {
                if(obj1 == null || obj2 == null){
                    throw new NullPointerException("compareTo: Argument passed is null");
                }
                Book book1 = (Book) obj1;
                Book book2 = (Book) obj2;
                return book1.isbn - book2.isbn;
            }
        });

 

Second Method

You define a class that implements Comparator like as below.

class BookComparator implements Comparator{
   
    public int compare(Object book1, Object book2){
   
        int b1= ((Book)book1).isbn;        
        int b2= ((Book)book2).isbn;
       
        if(b1> b2)
            return 1;
        else if(b1< b2)
            return -1;
        else
            return 0;    
    }
   
}

And use this newly defined comparator class as an argument to Collections.sort.

Arrays.sort(list, new BookComparator ());

Good reasons to use Comparator interface

  • I do not have permissions to edit the Book class.
  • Book class already implements Comparable interface, but I want to sort the objects using a different criteria
  • I want to have more than 1 criterias to sort the objects in different orders.

Reasons to implement Comparable interface

  • I want my class to have a default sorting criteria that can be used by the users of my class
  • Usually, one would like to sort the objects based on primary key

Few good links on this topic are here http://www.javadeveloper.co.in/java-example/java-comparator-example.htmlhttp://grdurand.com/static/presentation_four/comparable.htmlhttp://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

Interview questions — Serializable

Suppose I have 2 classes
1) Person having person name = “Yogesh”;
2) User having username = “User” extends Person and implements Serializable.

What will be the values printed if I serialize and deserialize the User object?

I guessed it wrongly and answered that personname will not get printed as Person class is not serializable. BUT THAT WAS WRONG !!!

Both the values will be stored and retrieved correctly. The reason I don’t know, but, this scenario, I have tested on PC