Daily Archives: January 23, 2016

Contain function() in hashSet

Today when I tried to solve a problem, I came across a weird problem. Look at below code:

public class test {

    static class Point {
        int a;
        public Point(int a) {
            this.a = a;
        }
    }

    public static void test1() {
        Point element = new Point(1);
        HashSet<Point> hs = new HashSet<Point>();
        hs.add(element);
        element.a = 2;
        System.out.println(hs.contains(element));
    }

    public static void test2() {
        HashSet<Integer> element = new HashSet<Integer>();
        HashSet<HashSet<Integer>> hs = new HashSet<HashSet<Integer>>();
        hs.add(element);
        element.add(2);
        System.out.println(hs.contains(element));
    }

    public static void main(String[] args) {
        test1();
        test2();
    }

}

test1 prints true, and test2 prints false. It is confusing. My friend junmin explained me the reason. Check code from JDK:

final Entry<K,V> getEntry(Object key) {
    if (size == 0) {
        return null;
    }

    int hash = (key == null) ? 0 : hash(key);
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

We can see contains() function both checks hashCode() and equals() function. Only when 2 functions return true, it will return true.

Accordingly, if I change the Point class to below, test1() will return false too.

static class Point {
    int a;
    public Point(int a) {
        this.a = a;
    }
    public int hashCode() {
        return a;
    }
}

Ideally, the element in HashSet() should be immutable. Or if we want to change, we should do remove, update, put operations.

Or another way is that we should guarantee that hashCode for new element should be the same as before, and new element should equal to before. But this is actually a worse way. Remember ideally, element in HashSet should be immutable.

 

Generate all combination of parenthesis

Given a number of pair parenthesis. Generate all combinations. For example n = 2, then should return ArrayList<String> = [“(())”, “()()”];

The solution is like below.

public static ArrayList<String> generateParenthesis(int n) {
    // Write your code here
    ArrayList<String> list = new ArrayList<String>();
    parenthesisHelper(0, 0, n, list, "");
    return list;
}

public static void parenthesisHelper(int open, int close, int pair, ArrayList<String> list, String ans) {
    if (close == pair) {
        list.add(ans);
        return;
    }
    if (open < pair) {
        parenthesisHelper(open + 1, close, pair, list, ans + "(");
    }
    if (close < open) {
        parenthesisHelper(open, close + 1, pair, list, ans + ")");
    }
}

This is a very beautiful recursion. Recursion rule is that number of open parenthesis should not be greater than pair number, number of close parenthesis shouldn’t be greater than number of open parenthesis.

my code on github: link

Number of Airplane in the sky

This problem is from lintcode.

Given an interval list which are flying and landing time of the flight. How many airplanes are on the sky at most?

Example

For interval list [[1,10],[2,3],[5,8],[4,7]], return 3

Note

If landing and flying happens at the same time, we consider landing should happen at first.

Solution. This is a very interesting problem. The solution is that we can treat start of interval as left parenthesis, end of interval as right parenthesis. The problem will change to find the deepest parenthesis. In order to find the deepest inside parenthesis, we count how many left parenthesis it has. Once there is a right parenthesis, number of left parenthesis decrease 1.

Below is an example to calculate. We can see the max left is 3.
numberofairplane

A tricky part is that we should take care of case of [[1, 3], [1, 3], [1, 3]]. This case return 3. In order to do that, I put <start, 1>, <end, -1> to a TreeMap. If there is already start in hashmap, then we should add <start, value_old + 1>. When we iterate all the parenthesis, we should add value instead 1 each time.

check my code on github: link